aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-05-23 04:13:20 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-05-23 04:13:20 +0000
commitc6794850a570a91c5f224b6f0293db9f560f4213 (patch)
tree3ac9924d8148451e27d3e3a2a74d515b8d7d4056
parent24fd6c8470f872ac95ce67d43f86129223c90bd3 (diff)
If the first argument of __builtin_object_size can be folded to a constant
pointer, but such folding encounters side-effects, ignore the side-effects rather than performing them at runtime: CodeGen generates wrong code for __builtin_object_size in that case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157310 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ExprConstant.cpp17
-rw-r--r--lib/CodeGen/CGBuiltin.cpp4
-rw-r--r--test/CodeGen/object-size.c5
3 files changed, 21 insertions, 5 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 5362320f49..d3ab84fc4a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -4319,10 +4319,16 @@ QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) {
}
bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) {
- // TODO: Perhaps we should let LLVM lower this?
LValue Base;
- if (!EvaluatePointer(E->getArg(0), Base, Info))
- return false;
+
+ {
+ // The operand of __builtin_object_size is never evaluated for side-effects.
+ // If there are any, but we can determine the pointed-to object anyway, then
+ // ignore the side-effects.
+ SpeculativeEvaluationRAII SpeculativeEval(Info);
+ if (!EvaluatePointer(E->getArg(0), Base, Info))
+ return false;
+ }
// If we can prove the base is null, lower to zero now.
if (!Base.getLValueBase()) return Success(0, E);
@@ -4355,13 +4361,16 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
return true;
// If evaluating the argument has side-effects we can't determine
- // the size of the object and lower it to unknown now.
+ // the size of the object and lower it to unknown now. CodeGen relies on
+ // us to handle all cases where the expression has side-effects.
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);
return Success(0, E);
}
+ // Expression had no side effects, but we couldn't statically determine the
+ // size of the referenced object.
return Error(E);
}
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 944fbe9f19..a3d4af72da 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -335,6 +335,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, ArgValue));
}
case Builtin::BI__builtin_object_size: {
+ // We rely on constant folding to deal with expressions with side effects.
+ assert(!E->getArg(0)->HasSideEffects(getContext()) &&
+ "should have been constant folded");
+
// We pass this builtin onto the optimizer so that it can
// figure out the object size in more complex cases.
llvm::Type *ResType = ConvertType(E->getType());
diff --git a/test/CodeGen/object-size.c b/test/CodeGen/object-size.c
index 1f16d02d7d..df6189ef10 100644
--- a/test/CodeGen/object-size.c
+++ b/test/CodeGen/object-size.c
@@ -55,7 +55,10 @@ void test6() {
// CHECK: define void @test7
void test7() {
int i;
- // CHECK: = call i64 @llvm.objectsize.i64(i8* {{.*}}@gbuf{{.*}}, i1 false)
+ // Ensure we only evaluate the side-effect once.
+ // CHECK: = add
+ // CHECK-NOT: = add
+ // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 63)
strcpy((++i, gbuf), "Hi there");
}