Skip to content

Commit c0a8bc2

Browse files
committed
Merge branch 'master-post-microsoft' into addclang
2 parents addfe37 + eeaf25a commit c0a8bc2

17 files changed

+390
-25
lines changed

clang/include/clang/3C/ConstraintVariables.h

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class ConstraintVariable {
8686
// to be used inside an itype
8787
virtual std::string mkString(const EnvironmentMap &E, bool EmitName = true,
8888
bool ForItype = false,
89-
bool EmitPointee = false) const = 0;
89+
bool EmitPointee = false, bool UnmaskTypedef = false) const = 0;
9090

9191
// Debug printing of the constraint variable.
9292
virtual void print(llvm::raw_ostream &O) const = 0;
@@ -181,6 +181,17 @@ bool isAValidPVConstraint(const ConstraintVariable *C);
181181
class PointerVariableConstraint;
182182
class FunctionVariableConstraint;
183183

184+
// We need to store the level inside the type AST at which the first
185+
// typedef occurs. This allows us to stop rewriting once we hit the
186+
// first typedef. (All subsequent typedefs will not be rewritten, as
187+
// rewriting will stop)
188+
struct InternalTypedefInfo {
189+
bool hasTypedef;
190+
int typedefLevel;
191+
std::string typedefName;
192+
};
193+
194+
184195
// Represents an individual constraint on a pointer variable.
185196
// This could contain a reference to a FunctionVariableConstraint
186197
// in the case of a function pointer declaration.
@@ -261,6 +272,18 @@ class PointerVariableConstraint : public ConstraintVariable {
261272
// pointers.
262273
bool IsZeroWidthArray;
263274

275+
// Was this variable a checked pointer in the input program?
276+
// This is important for two reasons: (1) externs that are checked should be
277+
// kept that way during solving, (2) nothing that was originally checked
278+
// should be modified during rewriting.
279+
bool OriginallyChecked;
280+
281+
bool IsTypedef = false;
282+
TypedefNameDecl* TDT;
283+
std::string typedefString;
284+
// Does the type internally contain a typedef, and if so: at what level and what is it's name?
285+
struct InternalTypedefInfo typedeflevelinfo;
286+
264287
public:
265288
// Constructor for when we know a CVars and a type string.
266289
PointerVariableConstraint(CAtoms V, std::string T, std::string Name,
@@ -278,6 +301,9 @@ class PointerVariableConstraint : public ConstraintVariable {
278301
// Check if any of the pointers is either a sized or unsized arr.
279302
bool hasSomeSizedArr() const;
280303

304+
bool isTypedef(void);
305+
void setTypedef(TypedefNameDecl *TypedefType, std::string);
306+
281307
// Is an itype present for this constraint? If yes,
282308
// what is the text of that itype?
283309
bool hasItype() const override { return ItypeStr.size() > 0; }
@@ -335,7 +361,9 @@ class PointerVariableConstraint : public ConstraintVariable {
335361

336362
std::string mkString(const EnvironmentMap &E, bool EmitName = true,
337363
bool ForItype = false,
338-
bool EmitPointee = false) const override;
364+
bool EmitPointee = false,
365+
bool UnmaskTypedef = false)
366+
const override;
339367

340368
FunctionVariableConstraint *getFV() const { return FV; }
341369

@@ -448,7 +476,9 @@ class FunctionVariableConstraint : public ConstraintVariable {
448476

449477
std::string mkString(const EnvironmentMap &E, bool EmitName = true,
450478
bool ForItype = false,
451-
bool EmitPointee = false) const override;
479+
bool EmitPointee = false,
480+
bool UnmaskTypedef = false)
481+
const override;
452482
void print(llvm::raw_ostream &O) const override;
453483
void dump() const override { print(llvm::errs()); }
454484
void dumpJson(llvm::raw_ostream &O) const override;

clang/include/clang/3C/DeclRewriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class DeclRewriter {
6969
void doDeclRewrite(SourceRange &SR, DeclReplacement *N);
7070

7171
void rewriteFunctionDecl(FunctionDeclReplacement *N);
72+
void rewriteTypedefDecl(TypedefDeclReplacement *TDT, RSet &ToRewrite);
7273
void getDeclsOnSameLine(DeclReplacement *N, std::vector<Decl *> &Decls);
7374
bool isSingleDeclaration(DeclReplacement *N);
7475
bool areDeclarationsOnSameLine(DeclReplacement *N1, DeclReplacement *N2);

clang/include/clang/3C/ProgramInfo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,30 @@ class ProgramInfo : public ProgramVariableAdder {
110110
void constrainWildIfMacro(ConstraintVariable *CV, SourceLocation Location,
111111
PersistentSourceLoc *PSL = nullptr);
112112

113+
114+
void unifyIfTypedef(const clang::Type*, clang::ASTContext&,
115+
clang::DeclaratorDecl*, PVConstraint*);
116+
117+
std::pair<CVarSet, bool> lookupTypedef(PersistentSourceLoc PSL);
118+
119+
bool seenTypedef(PersistentSourceLoc PSL);
120+
121+
void addTypedef(PersistentSourceLoc PSL, bool ShouldCheck);
122+
113123
private:
114124
// List of constraint variables for declarations, indexed by their location in
115125
// the source. This information persists across invocations of the constraint
116126
// analysis from compilation unit to compilation unit.
117127
VariableMap Variables;
118128

129+
// Map storing constraint information for typedefed types
130+
// The set contains all the constraint variables that also use this tyepdef
131+
// TODO this could be replaced w/ a signle CVar
132+
// The bool informs the rewriter whether or not this typedef should be
133+
// rewritten. It will be false for typedefs we don't support rewritting,
134+
// such as typedefs that are pointers to anonymous structs
135+
std::map<PersistentSourceLoc, std::pair<CVarSet, bool>> typedefVars;
136+
119137
// Map with the same purpose as the Variables map, this stores constraint
120138
// variables for non-declaration expressions.
121139
std::map<PersistentSourceLoc, CVarSet> ExprConstraintVars;

clang/include/clang/3C/RewriteUtils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class DeclReplacement {
3333
}
3434

3535
// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
36-
enum DRKind { DRK_VarDecl, DRK_ParmVarDecl, DRK_FunctionDecl, DRK_FieldDecl };
36+
enum DRKind { DRK_VarDecl, DRK_ParmVarDecl, DRK_FunctionDecl, DRK_FieldDecl, DRK_TypedefDecl };
3737

3838
DRKind getKind() const { return Kind; }
3939

@@ -73,6 +73,8 @@ typedef DeclReplacementTempl<ParmVarDecl, DeclReplacement::DRK_ParmVarDecl>
7373
ParmVarDeclReplacement;
7474
typedef DeclReplacementTempl<FieldDecl, DeclReplacement::DRK_FieldDecl>
7575
FieldDeclReplacement;
76+
typedef DeclReplacementTempl<TypedefDecl, DeclReplacement::DRK_TypedefDecl>
77+
TypedefDeclReplacement;
7678

7779
class FunctionDeclReplacement
7880
: public DeclReplacementTempl<FunctionDecl,

clang/lib/3C/ConstraintBuilder.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// visitors create constraints based on the AST of the program.
1010
//===----------------------------------------------------------------------===//
1111

12+
#include <algorithm>
1213
#include "clang/3C/ConstraintBuilder.h"
1314
#include "clang/3C/3CGlobalOptions.h"
1415
#include "clang/3C/ArrayBoundsInferenceConsumer.h"
@@ -398,6 +399,52 @@ class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> {
398399
TypeVarInfo &TVInfo;
399400
};
400401

402+
class PtrToStructDef : public RecursiveASTVisitor<PtrToStructDef> {
403+
public:
404+
explicit PtrToStructDef(TypedefDecl *TDT) : TDT(TDT) {}
405+
406+
bool VisitPointerType(clang::PointerType *PT) {
407+
ispointer = true;
408+
return true;
409+
}
410+
411+
bool VisitRecordType(RecordType *RT) {
412+
auto decl = RT->getDecl();
413+
auto declRange = decl->getSourceRange();
414+
auto typedefRange = TDT->getSourceRange();
415+
bool declContained = (typedefRange.getBegin() < declRange.getBegin())
416+
&& !(typedefRange.getEnd() < typedefRange.getEnd());
417+
if (declContained) {
418+
structDefInTD = true;
419+
return false;
420+
} else {
421+
return true;
422+
}
423+
}
424+
425+
bool VisitFunctionProtoType(FunctionProtoType *FPT) {
426+
ispointer = true;
427+
return true;
428+
}
429+
430+
bool getResult(void) {
431+
return structDefInTD;
432+
}
433+
434+
static bool containsPtrToStructDef(TypedefDecl *TDT) {
435+
PtrToStructDef traverser(TDT);
436+
traverser.TraverseDecl(TDT);
437+
return traverser.getResult();
438+
}
439+
440+
private:
441+
TypedefDecl* TDT = nullptr;
442+
bool ispointer = false;
443+
bool structDefInTD = false;
444+
445+
};
446+
447+
401448
// This class visits a global declaration, generating constraints
402449
// for functions, variables, types, etc. that are visited
403450
class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> {
@@ -406,6 +453,20 @@ class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> {
406453
TypeVarInfo &TVI)
407454
: Context(Context), Info(I), CB(Info, Context), TVInfo(TVI) {}
408455

456+
bool VisitTypedefDecl(TypedefDecl* TD) {
457+
CVarSet empty;
458+
auto PSL = PersistentSourceLoc::mkPSL(TD, *Context);
459+
// If we haven't seen this typedef before, initialize it's entry in the
460+
// typedef map. If we have seen it before, and we need to preserve the
461+
// constraints contained within it
462+
if (!Info.seenTypedef(PSL))
463+
// Add this typedef to the program info, if it contains a ptr to
464+
// an anonymous struct we mark as not being rewritable
465+
Info.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD));
466+
467+
return true;
468+
}
469+
409470
bool VisitVarDecl(VarDecl *G) {
410471

411472
if (G->hasGlobalStorage() && isPtrOrArrayType(G->getType())) {
@@ -485,7 +546,8 @@ class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> {
485546
class VariableAdderVisitor : public RecursiveASTVisitor<VariableAdderVisitor> {
486547
public:
487548
explicit VariableAdderVisitor(ASTContext *Context, ProgramVariableAdder &VA)
488-
: Context(Context), VarAdder(VA) {}
549+
: Context(Context), VarAdder(VA) {}
550+
489551

490552
bool VisitVarDecl(VarDecl *D) {
491553
FullSourceLoc FL = Context->getFullLoc(D->getBeginLoc());
@@ -542,6 +604,7 @@ void ConstraintBuilderConsumer::HandleTranslationUnit(ASTContext &C) {
542604
errs() << "Analyzing\n";
543605
}
544606

607+
545608
VariableAdderVisitor VAV = VariableAdderVisitor(&C, Info);
546609
TypeVarVisitor TV = TypeVarVisitor(&C, Info);
547610
ConstraintResolver CSResolver(Info, &C);

clang/lib/3C/ConstraintVariables.cpp

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <sstream>
1919

2020
using namespace clang;
21+
// Macro for boolean implication
22+
#define IMPLIES(a,b) ((a) ? (b) : true)
2123

2224
static llvm::cl::OptionCategory OptimizationCategory("Optimization category");
2325
static llvm::cl::opt<bool>
@@ -112,8 +114,58 @@ PointerVariableConstraint::PointerVariableConstraint(
112114

113115
PointerVariableConstraint::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

118170
PointerVariableConstraint::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+
557623
std::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

12281304
std::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

Comments
 (0)