1818#include < sstream>
1919
2020using namespace clang ;
21+ // Macro for boolean implication
22+ #define IMPLIES (a,b ) ((a) ? (b) : true )
2123
2224static llvm::cl::OptionCategory OptimizationCategory (" Optimization category" );
2325static llvm::cl::opt<bool >
@@ -112,8 +114,58 @@ PointerVariableConstraint::PointerVariableConstraint(
112114
113115PointerVariableConstraint::PointerVariableConstraint (DeclaratorDecl *D,
114116 ProgramInfo &I,
115- const ASTContext &C)
116- : PointerVariableConstraint(D->getType (), D, D->getName(), I, C) {}
117+ const ASTContext &C) :
118+ PointerVariableConstraint(D->getType (), D, D->getName(),
119+ I, C) { }
120+
121+
122+ // Simple recursive visitor for determining if a type contains a typedef
123+ // entrypoint is find()
124+ class TypedefLevelFinder : public RecursiveASTVisitor <TypedefLevelFinder> {
125+ public:
126+
127+ static struct InternalTypedefInfo find (const QualType &QT) {
128+ TypedefLevelFinder TLF;
129+ QualType tosearch;
130+ // If the type is currently a typedef, desugar that.
131+ // This is so we can see if the type _contains_ a typedef
132+ if (auto TDT = dyn_cast<TypedefType>(QT))
133+ tosearch = TDT->desugar ();
134+ else
135+ tosearch = QT;
136+ TLF.TraverseType (tosearch);
137+ // If we found a typedef the we need to have filled out the name field
138+ assert (IMPLIES (TLF.hastypedef , TLF.TDname != " " ));
139+ struct InternalTypedefInfo info =
140+ { TLF.hastypedef , TLF.typedeflevel , TLF.TDname };
141+ return info;
142+ }
143+
144+ bool VisitTypedefType (TypedefType *TT) {
145+ hastypedef = true ;
146+ auto TDT = TT->getDecl ();
147+ TDname = TDT->getNameAsString ();
148+ return false ;
149+ }
150+
151+ bool VisitPointerType (PointerType *PT) {
152+ typedeflevel++;
153+ return true ;
154+ }
155+
156+ bool VisitArrayType (ArrayType *AT) {
157+ typedeflevel++;
158+ return true ;
159+ }
160+
161+
162+ private:
163+ int typedeflevel = 0 ;
164+ std::string TDname = " " ;
165+ bool hastypedef = false ;
166+
167+ };
168+
117169
118170PointerVariableConstraint::PointerVariableConstraint (
119171 const QualType &QT, DeclaratorDecl *D, std::string N, ProgramInfo &I,
@@ -125,6 +177,7 @@ PointerVariableConstraint::PointerVariableConstraint(
125177 QualType QTy = QT;
126178 const Type *Ty = QTy.getTypePtr ();
127179 auto &CS = I.getConstraints ();
180+ typedeflevelinfo = TypedefLevelFinder::find (QT);
128181 // If the type is a decayed type, then maybe this is the result of
129182 // decaying an array to a pointer. If the original type is some
130183 // kind of array type, we want to use that instead.
@@ -551,12 +604,29 @@ void PointerVariableConstraint::addArrayAnnotations(
551604 assert (CheckedArrs.empty ());
552605}
553606
607+
608+ bool PointerVariableConstraint::isTypedef (void ) {
609+ return IsTypedef;
610+ }
611+
612+ void PointerVariableConstraint::setTypedef (TypedefNameDecl* T, std::string s) {
613+ IsTypedef = true ;
614+ TDT = T;
615+ typedefString = s;
616+ }
617+
618+
554619// Mesh resolved constraints with the PointerVariableConstraints set of
555620// variables and potentially nested function pointer declaration. Produces a
556621// string that can be replaced in the source code.
622+
557623std::string PointerVariableConstraint::mkString (const EnvironmentMap &E,
558624 bool EmitName, bool ForItype,
559- bool EmitPointee) const {
625+ bool EmitPointee, bool UnmaskTypedef) const {
626+ if (IsTypedef && !UnmaskTypedef) {
627+ return typedefString + (EmitName && getName () != RETVAR ? (" " + getName ()) : " " );
628+ }
629+
560630 std::ostringstream Ss;
561631 // This deque will store all the type strings that need to pushed
562632 // to the end of the type string. This is typically things like
@@ -581,11 +651,14 @@ std::string PointerVariableConstraint::mkString(const EnvironmentMap &E,
581651 uint32_t TypeIdx = 0 ;
582652
583653 auto It = Vars.begin ();
654+ auto i = 0 ;
584655 // Skip over first pointer level if only emitting pointee string.
585656 // This is needed when inserting type arguments.
586657 if (EmitPointee)
587658 ++It;
588- for (; It != Vars.end (); ++It) {
659+ // Interate through the vars(), but if we have an internal typedef, then stop once you reach the
660+ // typedef's level
661+ for (; It != Vars.end () && IMPLIES (typedeflevelinfo.hasTypedef , i < typedeflevelinfo.typedefLevel ); ++It, i++) {
589662 const auto &V = *It;
590663 ConstAtom *C = nullptr ;
591664 if (ConstAtom *CA = dyn_cast<ConstAtom>(V)) {
@@ -708,6 +781,9 @@ std::string PointerVariableConstraint::mkString(const EnvironmentMap &E,
708781 // type.
709782 if (FV) {
710783 Ss << FV->mkString (E);
784+ } else if (typedeflevelinfo.hasTypedef ) {
785+ auto name = typedeflevelinfo.typedefName ;
786+ Ss << name;
711787 } else {
712788 Ss << BaseType;
713789 }
@@ -1227,7 +1303,7 @@ bool FunctionVariableConstraint::solutionEqualTo(
12271303
12281304std::string FunctionVariableConstraint::mkString (const EnvironmentMap &E,
12291305 bool EmitName, bool ForItype,
1230- bool EmitPointee) const {
1306+ bool EmitPointee, bool UnmaskTypedef ) const {
12311307 std::string Ret = " " ;
12321308 Ret = ReturnVar->mkString (E);
12331309 Ret = Ret + " (" ;
0 commit comments