|  | 
| 21 | 21 | using namespace llvm; | 
| 22 | 22 | using namespace clang; | 
| 23 | 23 | 
 | 
| 24 |  | -// This class is intended to locate inline struct definitions | 
| 25 |  | -// in order to mark them wild or signal a warning as appropriate. | 
| 26 |  | -class InlineStructDetector { | 
| 27 |  | -public: | 
| 28 |  | -  explicit InlineStructDetector() : LastRecordDecl(nullptr) {} | 
| 29 |  | - | 
| 30 |  | -  void processRecordDecl(RecordDecl *Declaration, ProgramInfo &Info, | 
| 31 |  | -                         ASTContext *Context, ConstraintResolver CB) { | 
| 32 |  | -    LastRecordDecl = Declaration; | 
| 33 |  | -    if (RecordDecl *Definition = Declaration->getDefinition()) { | 
| 34 |  | -      auto LastRecordLocation = Definition->getBeginLoc(); | 
| 35 |  | -      FullSourceLoc FL = Context->getFullLoc(Definition->getBeginLoc()); | 
| 36 |  | -      if (FL.isValid()) { | 
| 37 |  | -        SourceManager &SM = Context->getSourceManager(); | 
| 38 |  | -        FileID FID = FL.getFileID(); | 
| 39 |  | -        const FileEntry *FE = SM.getFileEntryForID(FID); | 
| 40 |  | - | 
| 41 |  | -        // Detect whether this RecordDecl is part of an inline struct. | 
| 42 |  | -        bool IsInLineStruct = false; | 
| 43 |  | -        Decl *D = Declaration->getNextDeclInContext(); | 
| 44 |  | -        if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) { | 
| 45 |  | -          auto VarTy = VD->getType(); | 
| 46 |  | -          auto BeginLoc = VD->getBeginLoc(); | 
| 47 |  | -          auto EndLoc = VD->getEndLoc(); | 
| 48 |  | -          SourceManager &SM = Context->getSourceManager(); | 
| 49 |  | -          IsInLineStruct = | 
| 50 |  | -              !isPtrOrArrayType(VarTy) && !VD->hasInit() && | 
| 51 |  | -              SM.isPointWithin(LastRecordLocation, BeginLoc, EndLoc); | 
| 52 |  | -        } | 
| 53 |  | - | 
| 54 |  | -        if (FE && FE->isValid()) { | 
| 55 |  | -          // We only want to re-write a record if it contains | 
| 56 |  | -          // any pointer types, to include array types. | 
| 57 |  | -          for (const auto &F : Definition->fields()) { | 
| 58 |  | -            auto FieldTy = F->getType(); | 
| 59 |  | -            // If the RecordDecl is a union or in a system header | 
| 60 |  | -            // and this field is a pointer, we need to mark it wild. | 
| 61 |  | -            bool FieldInUnionOrSysHeader = | 
| 62 |  | -                (FL.isInSystemHeader() || Definition->isUnion()); | 
| 63 |  | -            // Mark field wild if the above is true and the field is a pointer. | 
| 64 |  | -            if (isPtrOrArrayType(FieldTy) && | 
| 65 |  | -                (FieldInUnionOrSysHeader || IsInLineStruct)) { | 
| 66 |  | -              std::string Rsn = "Union or external struct field encountered"; | 
| 67 |  | -              CVarOption CV = Info.getVariable(F, Context); | 
| 68 |  | -              CB.constraintCVarToWild(CV, Rsn); | 
| 69 |  | -            } | 
| 70 |  | -          } | 
| 71 |  | -        } | 
| 72 |  | -      } | 
| 73 |  | -    } | 
| 74 |  | -  } | 
| 75 |  | - | 
| 76 |  | -  void processVarDecl(VarDecl *VD, ProgramInfo &Info, ASTContext *Context, | 
| 77 |  | -                      ConstraintResolver CB) { | 
| 78 |  | -    // If the last seen RecordDecl is non-null and coincides with the current | 
| 79 |  | -    // VarDecl (i.e. via an inline struct), we proceed as follows: | 
| 80 |  | -    // If the struct is named, do nothing. | 
| 81 |  | -    // If the struct is anonymous: | 
| 82 |  | -    //      When alltypes is on, do nothing, but signal a warning to | 
| 83 |  | -    //                           the user indicating its presence. | 
| 84 |  | -    //      When alltypes is off, mark the VarDecl WILD in order to | 
| 85 |  | -    //                           ensure the converted program compiles. | 
| 86 |  | -    if (LastRecordDecl != nullptr) { | 
| 87 |  | -      auto LastRecordLocation = LastRecordDecl->getBeginLoc(); | 
| 88 |  | -      auto BeginLoc = VD->getBeginLoc(); | 
| 89 |  | -      auto EndLoc = VD->getEndLoc(); | 
| 90 |  | -      auto VarTy = VD->getType(); | 
| 91 |  | -      SourceManager &SM = Context->getSourceManager(); | 
| 92 |  | -      bool IsInLineStruct = | 
| 93 |  | -          SM.isPointWithin(LastRecordLocation, BeginLoc, EndLoc) && | 
| 94 |  | -          isPtrOrArrayType(VarTy); | 
| 95 |  | -      bool IsNamedInLineStruct = | 
| 96 |  | -          IsInLineStruct && LastRecordDecl->getNameAsString() != ""; | 
| 97 |  | -      if (IsInLineStruct && !IsNamedInLineStruct) { | 
| 98 |  | -        if (!_3COpts.AllTypes) { | 
| 99 |  | -          CVarOption CV = Info.getVariable(VD, Context); | 
| 100 |  | -          CB.constraintCVarToWild(CV, "Inline struct encountered."); | 
| 101 |  | -        } else { | 
| 102 |  | -          reportCustomDiagnostic(Context->getDiagnostics(), | 
| 103 |  | -                                 DiagnosticsEngine::Warning, | 
| 104 |  | -                                 "\n Rewriting failed" | 
| 105 |  | -                                 "for %q0 because an inline " | 
| 106 |  | -                                 "or anonymous struct instance " | 
| 107 |  | -                                 "was detected.\n Consider manually " | 
| 108 |  | -                                 "rewriting by inserting the struct " | 
| 109 |  | -                                 "definition inside the _Ptr " | 
| 110 |  | -                                 "annotation.\n " | 
| 111 |  | -                                 "EX. struct {int *a; int *b;} x; " | 
| 112 |  | -                                 "_Ptr<struct {int *a; _Ptr<int> b;}>;", | 
| 113 |  | -                                 VD->getLocation()) | 
| 114 |  | -              << VD; | 
| 115 |  | -        } | 
| 116 |  | -      } | 
| 117 |  | -    } | 
| 118 |  | -  } | 
| 119 |  | - | 
| 120 |  | -private: | 
| 121 |  | -  RecordDecl *LastRecordDecl; | 
| 122 |  | -}; | 
| 123 |  | - | 
| 124 | 24 | // This class visits functions and adds constraints to the | 
| 125 | 25 | // Constraints instance assigned to it. | 
| 126 | 26 | // Each VisitXXX method is responsible for looking inside statements | 
| 127 | 27 | // and imposing constraints on variables it uses | 
| 128 | 28 | class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> { | 
| 129 | 29 | public: | 
| 130 | 30 |   explicit FunctionVisitor(ASTContext *C, ProgramInfo &I, FunctionDecl *FD) | 
| 131 |  | -      : Context(C), Info(I), Function(FD), CB(Info, Context), | 
| 132 |  | -        ISD() {} | 
|  | 31 | +      : Context(C), Info(I), Function(FD), CB(Info, Context) {} | 
| 133 | 32 | 
 | 
| 134 | 33 |   // T x = e | 
| 135 | 34 |   bool VisitDeclStmt(DeclStmt *S) { | 
| 136 | 35 |     // Introduce variables as needed. | 
| 137 |  | -    for (const auto &D : S->decls()) { | 
| 138 |  | -      if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { | 
| 139 |  | -        ISD.processRecordDecl(RD, Info, Context, CB); | 
| 140 |  | -      } | 
| 141 |  | -      if (VarDecl *VD = dyn_cast<VarDecl>(D)) { | 
| 142 |  | -        if (VD->isLocalVarDecl()) { | 
| 143 |  | -          FullSourceLoc FL = Context->getFullLoc(VD->getBeginLoc()); | 
| 144 |  | -          SourceRange SR = VD->getSourceRange(); | 
| 145 |  | -          if (SR.isValid() && FL.isValid() && isPtrOrArrayType(VD->getType())) { | 
| 146 |  | -            ISD.processVarDecl(VD, Info, Context, CB); | 
| 147 |  | -          } | 
| 148 |  | -        } | 
| 149 |  | -      } | 
| 150 |  | -    } | 
| 151 | 36 | 
 | 
| 152 | 37 |     // Process inits even for non-pointers because structs and union values | 
| 153 | 38 |     // can contain pointers | 
| @@ -433,7 +318,6 @@ class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> { | 
| 433 | 318 |   ProgramInfo &Info; | 
| 434 | 319 |   FunctionDecl *Function; | 
| 435 | 320 |   ConstraintResolver CB; | 
| 436 |  | -  InlineStructDetector ISD; | 
| 437 | 321 | }; | 
| 438 | 322 | 
 | 
| 439 | 323 | class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> { | 
| @@ -482,15 +366,14 @@ class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> { | 
| 482 | 366 | class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> { | 
| 483 | 367 | public: | 
| 484 | 368 |   explicit ConstraintGenVisitor(ASTContext *Context, ProgramInfo &I) | 
| 485 |  | -      : Context(Context), Info(I), CB(Info, Context), ISD() {} | 
|  | 369 | +      : Context(Context), Info(I), CB(Info, Context) {} | 
| 486 | 370 | 
 | 
| 487 | 371 |   bool VisitVarDecl(VarDecl *G) { | 
| 488 | 372 | 
 | 
| 489 | 373 |     if (G->hasGlobalStorage() && isPtrOrArrayType(G->getType())) { | 
| 490 | 374 |       if (G->hasInit()) { | 
| 491 | 375 |         CB.constrainLocalAssign(nullptr, G, G->getInit(), Same_to_Same); | 
| 492 | 376 |       } | 
| 493 |  | -      ISD.processVarDecl(G, Info, Context, CB); | 
| 494 | 377 |     } | 
| 495 | 378 |     return true; | 
| 496 | 379 |   } | 
| @@ -537,16 +420,10 @@ class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> { | 
| 537 | 420 |     return true; | 
| 538 | 421 |   } | 
| 539 | 422 | 
 | 
| 540 |  | -  bool VisitRecordDecl(RecordDecl *Declaration) { | 
| 541 |  | -    ISD.processRecordDecl(Declaration, Info, Context, CB); | 
| 542 |  | -    return true; | 
| 543 |  | -  } | 
| 544 |  | - | 
| 545 | 423 | private: | 
| 546 | 424 |   ASTContext *Context; | 
| 547 | 425 |   ProgramInfo &Info; | 
| 548 | 426 |   ConstraintResolver CB; | 
| 549 |  | -  InlineStructDetector ISD; | 
| 550 | 427 | }; | 
| 551 | 428 | 
 | 
| 552 | 429 | // Some information about variables in the program is required by the type | 
|  | 
0 commit comments