From: Richard Smith Date: Wed, 23 May 2012 04:13:20 +0000 (+0000) Subject: If the first argument of __builtin_object_size can be folded to a constant X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c6794850a570a91c5f224b6f0293db9f560f4213;p=clang 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 --- 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"); }