]> granicus.if.org Git - clang/commitdiff
If the first argument of __builtin_object_size can be folded to a constant
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 23 May 2012 04:13:20 +0000 (04:13 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 23 May 2012 04:13:20 +0000 (04:13 +0000)
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

lib/AST/ExprConstant.cpp
lib/CodeGen/CGBuiltin.cpp
test/CodeGen/object-size.c

index 5362320f4997a834c4822b5f5952cb46ba22a35a..d3ab84fc4a8cf9c4a582965dd46f851bebdd0f00 100644 (file)
@@ -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);
   }
 
index 944fbe9f19a450824a4756e1876857de5b4cc8dc..a3d4af72da16e91b9820898726167d476322b27d 100644 (file)
@@ -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());
index 1f16d02d7d64fa6de1e7cc8ec344da588d3cb24f..df6189ef10d3641c6f8f54bc2f9eb657996dc00f 100644 (file)
@@ -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");
 }