Skip to content

Commit 782449d

Browse files
Rewrite types in explict cast expressions
1 parent 2c3c217 commit 782449d

32 files changed

+139
-102
lines changed

clang/include/clang/CConv/ConstraintResolver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class ConstraintResolver {
7070
bool hasPersistentConstraints(clang::Expr *E);
7171
CVarSet getPersistentConstraints(clang::Expr *E);
7272
void storePersistentConstraints(clang::Expr *E, CVarSet &Vars);
73+
PVConstraint *getRewritablePVConstraint(Expr *E);
7374
};
7475

7576
#endif // _CONSTRAINTRESOLVER_H

clang/include/clang/CConv/ProgramInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class ProgramInfo {
110110
bool hasTypeParamBindings(CallExpr *CE, ASTContext *C);
111111
CallTypeParamBindingsT &getTypeParamBindings(CallExpr *CE, ASTContext *C);
112112

113+
void constrainWildIfMacro(CVarSet &S, SourceLocation Location);
114+
113115
private:
114116
// List of all constraint variables, indexed by their location in the source.
115117
// This information persists across invocations of the constraint analysis
@@ -175,8 +177,6 @@ class ProgramInfo {
175177
// or global)
176178
std::set<FVConstraint *> *getFuncFVConstraints(FunctionDecl *FD,
177179
ASTContext *C);
178-
void constrainWildIfMacro(CVarSet S,
179-
SourceLocation Location);
180180
};
181181

182182
#endif

clang/lib/CConv/CastPlacement.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ using namespace clang;
2626

2727
bool CastPlacementVisitor::VisitCallExpr(CallExpr *CE) {
2828
Decl *D = CE->getCalleeDecl();
29-
if (D) {
29+
if (Rewriter::isRewritable(CE->getExprLoc()) && D) {
3030
PersistentSourceLoc PL = PersistentSourceLoc::mkPSL(CE, *Context);
3131
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
3232
// Get the constraint variable for the function.

clang/lib/CConv/ConstraintResolver.cpp

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,10 @@ CVarSet
214214
return PVConstraintFromType(TypE);
215215
}
216216
// NULL
217-
} else if (isNULLExpression(E, *Context)) {
217+
// Special handling for casts of null is required to enable rewriting
218+
// statements such as int *x = (int*) 0. If this was handled as a
219+
// normal null expression, the cast would never be visited.
220+
} else if (!isa<ExplicitCastExpr>(E) && isNULLExpression(E, *Context)) {
218221
return EmptyCSet;
219222
// Implicit cast, e.g., T* from T[] or int (*)(int) from int (int),
220223
// but also weird int->int * conversions (and back)
@@ -254,14 +257,29 @@ CVarSet
254257
CVarSet Ret = EmptyCSet;
255258
if (ExplicitCastExpr *ECE = dyn_cast<ExplicitCastExpr>(E)) {
256259
assert(ECE->getType() == TypE);
257-
// Is cast internally safe? Return WILD if not
258260
Expr *TmpE = ECE->getSubExpr();
259-
if (TypE->isPointerType() && !isCastSafe(TypE, TmpE->getType()))
261+
// Is cast internally safe? Return WILD if not.
262+
// If the cast is NULL, it will otherwise seem invalid, but we want to
263+
// handle it as usual so the type in the cast can be rewritten.
264+
if (!isNULLExpression(ECE, *Context) && TypE->isPointerType()
265+
&& !isCastSafe(TypE, TmpE->getType())) {
260266
Ret = getInvalidCastPVCons(E);
261267
// NB: Expression ECE itself handled in
262268
// ConstraintBuilder::FunctionVisitor
263-
else
264-
Ret = getExprConstraintVars(TmpE);
269+
} else {
270+
CVarSet Vars = getExprConstraintVars(TmpE);
271+
// PVConstraint introduced for explicit cast so they can be rewritten.
272+
// Pretty much the same idea as CompoundLiteralExpr.
273+
PVConstraint *P = getRewritablePVConstraint(ECE);
274+
Ret = {P};
275+
// ConstraintVars for TmpE when ECE is NULL will be WILD, so
276+
// constraining GEQ these vars would be the cast always be WILD.
277+
if (!isNULLExpression(ECE, *Context)) {
278+
PersistentSourceLoc PL = PersistentSourceLoc::mkPSL(ECE, *Context);
279+
constrainConsVarGeq(Ret, Vars, Info.getConstraints(), &PL,
280+
Same_to_Same, false, &Info);
281+
}
282+
}
265283
}
266284
// x = y, x+y, x+=y, etc.
267285
else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
@@ -520,9 +538,7 @@ CVarSet
520538
CVarSet T;
521539
CVarSet Vars = getExprConstraintVars(CLE->getInitializer());
522540

523-
PVConstraint *P =
524-
new PVConstraint(CLE->getType(), nullptr, CLE->getStmtClassName(),
525-
Info, *Context, nullptr);
541+
PVConstraint *P = getRewritablePVConstraint(CLE);
526542
T = {P};
527543

528544
PersistentSourceLoc PL = PersistentSourceLoc::mkPSL(CLE, *Context);
@@ -581,11 +597,12 @@ CVarSet
581597
return Persist;
582598
}
583599

600+
584601
void ConstraintResolver::storePersistentConstraints(clang::Expr *E,
585602
CVarSet &Vars) {
586-
auto PSL = PersistentSourceLoc::mkPSL(E, *Context);
587603
// Store only if the PSL is valid.
588-
if (PSL.valid()) {
604+
auto PSL = PersistentSourceLoc::mkPSL(E, *Context);
605+
if (PSL.valid() && Rewriter::isRewritable(E->getBeginLoc())){
589606
CVarSet &Persist = Info.getPersistentConstraintVars(E, Context);
590607
Persist.insert(Vars.begin(), Vars.end());
591608
}
@@ -679,6 +696,18 @@ CVarSet ConstraintResolver::getBaseVarPVConstraint(DeclRefExpr *Decl) {
679696
return Ret;
680697
}
681698

699+
// Construct a PVConstraint for an expression that can safely be used when
700+
// rewriting the expression later on. This is done by making the constraint WILD
701+
// if the expression is inside a macro.
702+
PVConstraint *ConstraintResolver::getRewritablePVConstraint(Expr *E) {
703+
PVConstraint *P = new PVConstraint(E->getType(), nullptr,
704+
E->getStmtClassName(), Info, *Context,
705+
nullptr);
706+
CVarSet Tmp = {P};
707+
Info.constrainWildIfMacro(Tmp, E->getExprLoc());
708+
return P;
709+
}
710+
682711
bool
683712
ConstraintResolver::containsValidCons(CVarSet &CVs) {
684713
bool RetVal = false;

clang/lib/CConv/ProgramInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ CVarSet
641641
// If it was, we should constrain it to top. This is sad. Hopefully,
642642
// someday, the Rewriter will become less lame and let us re-write stuff
643643
// in macros.
644-
void ProgramInfo::constrainWildIfMacro(CVarSet S,
644+
void ProgramInfo::constrainWildIfMacro(CVarSet &S,
645645
SourceLocation Location) {
646646
std::string Rsn = "Pointer in Macro declaration.";
647647
if (!Rewriter::isRewritable(Location))

clang/lib/CConv/RewriteUtils.cpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -783,45 +783,52 @@ static void emit(Rewriter &R, ASTContext &C, std::set<FileID> &Files,
783783

784784

785785

786-
// Visit every array compound literal expression (i.e., (int*[2]){&a, &b}) and
787-
// replace the type name with a new type based on constraint solution.
788-
class CompoundLiteralRewriter
789-
: public clang::RecursiveASTVisitor<CompoundLiteralRewriter> {
786+
// Rewrites types that inside other expressions. This includes cast expression
787+
// and compound literal expressions.
788+
class TypeExprRewriter
789+
: public clang::RecursiveASTVisitor<TypeExprRewriter> {
790790
public:
791-
explicit CompoundLiteralRewriter(ASTContext *C, ProgramInfo &I, Rewriter &R)
791+
explicit TypeExprRewriter(ASTContext *C, ProgramInfo &I, Rewriter &R)
792792
: Context(C), Info(I) , Writer(R) {}
793793

794794
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *CLE) {
795-
// When an compound literal was visited in constraint generation, a
796-
// constraint variable for it was stored in program info. There should be
797-
// either zero or one of these.
798-
CVarSet
799-
CVSingleton = Info.getPersistentConstraintVars(CLE, Context);
795+
SourceRange TypeSrcRange(CLE->getBeginLoc().getLocWithOffset(1),
796+
CLE->getTypeSourceInfo()->getTypeLoc().getEndLoc());
797+
rewriteType(CLE, TypeSrcRange);
798+
return true;
799+
}
800+
801+
bool VisitCStyleCastExpr(CStyleCastExpr *ECE) {
802+
SourceRange TypeSrcRange
803+
(ECE->getBeginLoc().getLocWithOffset(1),
804+
ECE->getTypeInfoAsWritten()->getTypeLoc().getEndLoc());
805+
rewriteType(ECE, TypeSrcRange);
806+
return true;
807+
}
808+
809+
private:
810+
ASTContext *Context;
811+
ProgramInfo &Info;
812+
Rewriter &Writer;
813+
814+
void rewriteType(Expr *E, SourceRange &Range) {
815+
CVarSet CVSingleton = Info.getPersistentConstraintVars(E, Context);
800816
if (CVSingleton.empty())
801-
return true;
817+
return;
802818
ConstraintVariable *CV = getOnly(CVSingleton);
803819

804820
// Only rewrite if the type has changed.
805-
if(CV->anyChanges(Info.getConstraints().getVariables())){
821+
if (CV->anyChanges(Info.getConstraints().getVariables())){
806822
// The constraint variable is able to tell us what the new type string
807823
// should be.
808-
std::string NewType = CV->mkString(Info.getConstraints().getVariables(),false);
824+
std::string
825+
NewType = CV->mkString(Info.getConstraints().getVariables(), false);
809826

810827
// Replace the original type with this new one
811-
SourceRange *TypeSrcRange =
812-
new SourceRange(CLE->getBeginLoc().getLocWithOffset(1),
813-
CLE->getTypeSourceInfo()->getTypeLoc().getEndLoc());
814-
815-
if(canRewrite(Writer, *TypeSrcRange))
816-
Writer.ReplaceText(*TypeSrcRange, NewType);
828+
if (canRewrite(Writer, Range))
829+
Writer.ReplaceText(Range, NewType);
817830
}
818-
return true;
819831
}
820-
821-
private:
822-
ASTContext *Context;
823-
ProgramInfo &Info;
824-
Rewriter &Writer;
825832
};
826833

827834
// Adds type parameters to calls to alloc functions.
@@ -973,7 +980,7 @@ void RewriteConsumer::HandleTranslationUnit(ASTContext &Context) {
973980
CheckedRegionFinder CRF(&Context, R, Info, seen, nodeMap);
974981
CheckedRegionAdder CRA(&Context, R, nodeMap);
975982
CastPlacementVisitor ECPV(&Context, Info, R);
976-
CompoundLiteralRewriter CLR(&Context, Info, R);
983+
TypeExprRewriter TER(&Context, Info, R);
977984
TypeArgumentAdder TPA(&Context, Info, R);
978985
for (auto &D : TUD->decls()) {
979986
V.TraverseDecl(D);
@@ -986,7 +993,7 @@ void RewriteConsumer::HandleTranslationUnit(ASTContext &Context) {
986993
}
987994

988995
GVG.addGlobalDecl(dyn_cast<VarDecl>(D));
989-
CLR.TraverseDecl(D);
996+
TER.TraverseDecl(D);
990997
TPA.TraverseDecl(D);
991998
}
992999

clang/test/CheckedCRewriter/alloc_type_param.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ void foo() {
1919
// Explicit casts work fine also
2020

2121
int *d = (int*) malloc(sizeof(int));
22-
// CHECK: _Ptr<int> d = (int*) malloc<int>(sizeof(int));
22+
// CHECK: _Ptr<int> d = (_Ptr<int> ) malloc<int>(sizeof(int));
2323
int *e = (int*) calloc(1, sizeof(int));
24-
// CHECK: _Ptr<int> e = (int*) calloc<int>(1, sizeof(int));
24+
// CHECK: _Ptr<int> e = (_Ptr<int> ) calloc<int>(1, sizeof(int));
2525
int *f = (int*) realloc(d, sizeof(int));
26-
// CHECK: _Ptr<int> f = (int*) realloc<int>(d, sizeof(int));
26+
// CHECK: _Ptr<int> f = (_Ptr<int> ) realloc<int>(d, sizeof(int));
2727
}
2828

2929
// Allocating pointers to pointers

clang/test/CheckedCRewriter/allocator.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ void add_some_stuff(listhead *hd) {
4848
return;
4949
}
5050
//CHECK: void add_some_stuff(_Ptr<listhead> hd) {
51-
//CHECK-NEXT: _Ptr<listelt> l1 = (listelt *) malloc<listelt>(sizeof(listelt));
51+
//CHECK-NEXT: _Ptr<listelt> l1 = (_Ptr<listelt> ) malloc<listelt>(sizeof(listelt));

clang/test/CheckedCRewriter/b10_allsafepointerstruct.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct p *foo() {
5151
x->y = &ex2;
5252
y->y = &ex1;
5353
struct p *z = (struct p *) sus(x, y);
54-
//CHECK: _Ptr<struct p> z = (struct p *) sus(x, y);
54+
//CHECK: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
5555
return z;
5656
}
5757

@@ -67,6 +67,6 @@ struct p *bar() {
6767
x->y = &ex2;
6868
y->y = &ex1;
6969
struct p *z = (struct p *) sus(x, y);
70-
//CHECK: _Ptr<struct p> z = (struct p *) sus(x, y);
70+
//CHECK: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
7171
return z;
72-
}
72+
}

clang/test/CheckedCRewriter/b16_callerpointerstruct.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct p *foo() {
5454
x->y = &ex2;
5555
y->y = &ex1;
5656
struct p *z = (struct p *) sus(x, y);
57-
//CHECK_NOALL: _Ptr<struct p> z = (struct p *) sus(x, y);
57+
//CHECK_NOALL: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
5858
//CHECK_ALL: struct p *z = (struct p *) sus(x, y);
5959
return z;
6060
}
@@ -74,4 +74,4 @@ struct p *bar() {
7474
//CHECK: struct p *z = (struct p *) sus(x, y);
7575
z += 2;
7676
return z;
77-
}
77+
}

clang/test/CheckedCRewriter/b20_allsafepointerstructproto.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct p *foo() {
4646
x->y = &ex2;
4747
y->y = &ex1;
4848
struct p *z = (struct p *) sus(x, y);
49-
//CHECK: _Ptr<struct p> z = (struct p *) sus(x, y);
49+
//CHECK: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
5050
return z;
5151
}
5252

@@ -62,7 +62,7 @@ struct p *bar() {
6262
x->y = &ex2;
6363
y->y = &ex1;
6464
struct p *z = (struct p *) sus(x, y);
65-
//CHECK: _Ptr<struct p> z = (struct p *) sus(x, y);
65+
//CHECK: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
6666
return z;
6767
}
6868

@@ -72,4 +72,4 @@ struct p *sus(struct p *x, struct p *y) {
7272
struct p *z = malloc(sizeof(struct p));
7373
//CHECK: _Ptr<struct p> z = malloc<struct p>(sizeof(struct p));
7474
return z;
75-
}
75+
}

clang/test/CheckedCRewriter/b22_callerpointerstructproto.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct p *foo() {
4848
x->y = &ex2;
4949
y->y = &ex1;
5050
struct p *z = (struct p *) sus(x, y);
51-
//CHECK_NOALL: _Ptr<struct p> z = (struct p *) sus(x, y);
51+
//CHECK_NOALL: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
5252
//CHECK_ALL: struct p *z = (struct p *) sus(x, y);
5353
return z;
5454
}
@@ -78,4 +78,4 @@ struct p *sus(struct p *x, struct p *y) {
7878
//CHECK_NOALL: _Ptr<struct p> z = malloc<struct p>(sizeof(struct p));
7979
//CHECK_ALL: struct p *z = malloc<struct p>(sizeof(struct p));
8080
return z;
81-
}
81+
}

clang/test/CheckedCRewriter/b23_explicitunsafecast.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ int* foo() {
2929
int *y = &sy;
3030
//CHECK: _Ptr<int> y = &sy;
3131
int *z = (int *) sus(x, y);
32-
//CHECK: _Ptr<int> z = (int *) sus(x, y);
32+
//CHECK: _Ptr<int> z = (_Ptr<int> ) sus(x, y);
3333
*z = *z + 1;
3434
return z;
3535
}
@@ -44,4 +44,4 @@ char* bar() {
4444
char *z = (char *) (sus(x, y));
4545
//CHECK: char *z = (char *) (sus(x, y));
4646
return z;
47-
}
47+
}

clang/test/CheckedCRewriter/b24_implicitunsafecast.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ int* foo() {
2929
int *y = &sy;
3030
//CHECK: _Ptr<int> y = &sy;
3131
int *z = (int *) sus(x, y);
32-
//CHECK: _Ptr<int> z = (int *) sus(x, y);
32+
//CHECK: _Ptr<int> z = (_Ptr<int> ) sus(x, y);
3333
*z = *z + 1;
3434
return z;
3535
}
@@ -44,4 +44,4 @@ char* bar() {
4444
char *z = sus(x, y);
4545
//CHECK: char *z = sus(x, y);
4646
return z;
47-
}
47+
}

clang/test/CheckedCRewriter/b25_castprotosafe.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ int* foo() {
2222
int *y = &sy;
2323
//CHECK: _Ptr<int> y = &sy;
2424
int *z = (int *) sus(x, y);
25-
//CHECK: _Ptr<int> z = (int *) sus(x, y);
25+
//CHECK: _Ptr<int> z = (_Ptr<int> ) sus(x, y);
2626
*z = *z + 1;
2727
return z;
2828
}
@@ -35,7 +35,7 @@ int* bar() {
3535
int *y = &sy;
3636
//CHECK: _Ptr<int> y = &sy;
3737
int *z = (int *) (sus(x, y));
38-
//CHECK: _Ptr<int> z = (int *) (sus(x, y));
38+
//CHECK: _Ptr<int> z = (_Ptr<int> ) (sus(x, y));
3939
return z;
4040
}
4141

@@ -48,4 +48,4 @@ int *sus(int *x, int*y) {
4848
x++;
4949
*x = 2;
5050
return z;
51-
}
51+
}

0 commit comments

Comments
 (0)