|
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