Skip to content

Commit 8184556

Browse files
Remove all the old workarounds for unnamed structs.
Now that we automatically name them: - When -alltypes is on, we no longer need to warn that the multi-decl may be rewritten incorrectly. - When -alltypes is off, we no longer generate constraints to try to avoid the need to rewrite the multi-decl at all. InlineStructDetector did one thing unrelated to its name: it constrained all union fields wild. Move that logic to ProgramInfo::addVariable, make the constraint reason message more specific, and update root_cause.c to expect the new message.
1 parent 4bf6ff9 commit 8184556

File tree

3 files changed

+9
-127
lines changed

3 files changed

+9
-127
lines changed

clang/lib/3C/ConstraintBuilder.cpp

Lines changed: 2 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -21,133 +21,18 @@
2121
using namespace llvm;
2222
using namespace clang;
2323

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-
12424
// This class visits functions and adds constraints to the
12525
// Constraints instance assigned to it.
12626
// Each VisitXXX method is responsible for looking inside statements
12727
// and imposing constraints on variables it uses
12828
class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> {
12929
public:
13030
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) {}
13332

13433
// T x = e
13534
bool VisitDeclStmt(DeclStmt *S) {
13635
// 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-
}
15136

15237
// Process inits even for non-pointers because structs and union values
15338
// can contain pointers
@@ -433,7 +318,6 @@ class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> {
433318
ProgramInfo &Info;
434319
FunctionDecl *Function;
435320
ConstraintResolver CB;
436-
InlineStructDetector ISD;
437321
};
438322

439323
class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> {
@@ -482,15 +366,14 @@ class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> {
482366
class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> {
483367
public:
484368
explicit ConstraintGenVisitor(ASTContext *Context, ProgramInfo &I)
485-
: Context(Context), Info(I), CB(Info, Context), ISD() {}
369+
: Context(Context), Info(I), CB(Info, Context) {}
486370

487371
bool VisitVarDecl(VarDecl *G) {
488372

489373
if (G->hasGlobalStorage() && isPtrOrArrayType(G->getType())) {
490374
if (G->hasInit()) {
491375
CB.constrainLocalAssign(nullptr, G, G->getInit(), Same_to_Same);
492376
}
493-
ISD.processVarDecl(G, Info, Context, CB);
494377
}
495378
return true;
496379
}
@@ -537,16 +420,10 @@ class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> {
537420
return true;
538421
}
539422

540-
bool VisitRecordDecl(RecordDecl *Declaration) {
541-
ISD.processRecordDecl(Declaration, Info, Context, CB);
542-
return true;
543-
}
544-
545423
private:
546424
ASTContext *Context;
547425
ProgramInfo &Info;
548426
ConstraintResolver CB;
549-
InlineStructDetector ISD;
550427
};
551428

552429
// Some information about variables in the program is required by the type

clang/lib/3C/ProgramInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,11 @@ void ProgramInfo::addVariable(clang::DeclaratorDecl *D,
684684
unifyIfTypedef(QT, *AstContext, P);
685685
NewCV = P;
686686
NewCV->setValidDecl();
687+
if (FlD->getParent()->isUnion()) {
688+
// REVIEW: Should we also call NewCV->equateWithItype here? The previous
689+
// code in InlineStructDetector didn't call it.
690+
NewCV->constrainToWild(CS, "Union field encountered", &PLoc);
691+
}
687692
}
688693
} else
689694
llvm_unreachable("unknown decl type");

clang/test/3C/root_cause.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ void test1() {
4343

4444
union u {
4545
// unwritable-expected-warning@+1 {{0 unchecked pointers: Source code in non-writable file}}
46-
int *a; // expected-warning {{1 unchecked pointer: Union or external struct field encountered}}
46+
int *a; // expected-warning {{1 unchecked pointer: Union field encountered}}
4747
// unwritable-expected-warning@+1 {{0 unchecked pointers: Source code in non-writable file}}
48-
int *b; // expected-warning {{1 unchecked pointer: Union or external struct field encountered}}
48+
int *b; // expected-warning {{1 unchecked pointer: Union field encountered}}
4949
};
5050

5151
void (*c)(void); // unwritable-expected-warning {{0 unchecked pointers: Source code in non-writable file}}

0 commit comments

Comments
 (0)