diff options
-rw-r--r-- | lib/AST/ExprConstant.cpp | 17 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 4 | ||||
-rw-r--r-- | test/CodeGen/object-size.c | 5 |
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"); } |