|
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 (!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 |
@@ -432,7 +317,6 @@ class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> { |
432 | 317 | ProgramInfo &Info; |
433 | 318 | FunctionDecl *Function; |
434 | 319 | ConstraintResolver CB; |
435 | | - InlineStructDetector ISD; |
436 | 320 | }; |
437 | 321 |
|
438 | 322 | class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> { |
@@ -481,15 +365,14 @@ class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> { |
481 | 365 | class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> { |
482 | 366 | public: |
483 | 367 | explicit ConstraintGenVisitor(ASTContext *Context, ProgramInfo &I) |
484 | | - : Context(Context), Info(I), CB(Info, Context), ISD() {} |
| 368 | + : Context(Context), Info(I), CB(Info, Context) {} |
485 | 369 |
|
486 | 370 | bool VisitVarDecl(VarDecl *G) { |
487 | 371 |
|
488 | 372 | if (G->hasGlobalStorage() && isPtrOrArrayType(G->getType())) { |
489 | 373 | if (G->hasInit()) { |
490 | 374 | CB.constrainLocalAssign(nullptr, G, G->getInit(), Same_to_Same); |
491 | 375 | } |
492 | | - ISD.processVarDecl(G, Info, Context, CB); |
493 | 376 | } |
494 | 377 | return true; |
495 | 378 | } |
@@ -536,16 +419,10 @@ class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> { |
536 | 419 | return true; |
537 | 420 | } |
538 | 421 |
|
539 | | - bool VisitRecordDecl(RecordDecl *Declaration) { |
540 | | - ISD.processRecordDecl(Declaration, Info, Context, CB); |
541 | | - return true; |
542 | | - } |
543 | | - |
544 | 422 | private: |
545 | 423 | ASTContext *Context; |
546 | 424 | ProgramInfo &Info; |
547 | 425 | ConstraintResolver CB; |
548 | | - InlineStructDetector ISD; |
549 | 426 | }; |
550 | 427 |
|
551 | 428 | // Some information about variables in the program is required by the type |
|
0 commit comments