r245342 - Revert r245323, it caused PR24493.
Nico Weber via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 18 13:32:55 PDT 2015
Author: nico
Date: Tue Aug 18 15:32:55 2015
New Revision: 245342
URL: http://llvm.org/viewvc/llvm-project?rev=245342&view=rev
Log:
Revert r245323, it caused PR24493.
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/CodeGen/object-size.c
cfe/trunk/test/Sema/const-eval.c
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=245342&r1=245341&r2=245342&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Aug 18 15:32:55 2015
@@ -967,6 +967,10 @@ namespace {
// Check this LValue refers to an object. If not, set the designator to be
// invalid and emit a diagnostic.
bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) {
+ // Outside C++11, do not build a designator referring to a subobject of
+ // any object: we won't use such a designator for anything.
+ if (!Info.getLangOpts().CPlusPlus11)
+ Designator.setInvalid();
return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) &&
Designator.checkSubobject(Info, E, CSK);
}
@@ -2709,7 +2713,8 @@ static bool handleLValueToRValueConversi
// Check for special cases where there is no existing APValue to look at.
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
- if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) {
+ if (!LVal.Designator.Invalid && Base && !LVal.CallIndex &&
+ !Type.isVolatileQualified()) {
if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) {
// In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the
// initializer until now for such expressions. Such an expression can't be
@@ -5993,7 +5998,8 @@ public:
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
private:
- bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type);
+ static QualType GetObjectType(APValue::LValueBase B);
+ bool TryEvaluateBuiltinObjectSize(const CallExpr *E);
// FIXME: Missing: array subscript of vector, member of vector
};
} // end anonymous namespace
@@ -6165,7 +6171,7 @@ static bool EvaluateBuiltinConstantP(AST
/// Retrieves the "underlying object type" of the given expression,
/// as used by __builtin_object_size.
-static QualType getObjectType(APValue::LValueBase B) {
+QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) {
if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->getType();
@@ -6177,87 +6183,49 @@ static QualType getObjectType(APValue::L
return QualType();
}
-bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E,
- unsigned Type) {
- // Determine the denoted object.
+bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) {
LValue Base;
+
{
// 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);
- FoldConstant Fold(Info, true);
if (!EvaluatePointer(E->getArg(0), Base, Info))
return false;
}
- CharUnits BaseOffset = Base.getLValueOffset();
-
- // If we point to before the start of the object, there are no
- // accessible bytes.
- if (BaseOffset < CharUnits::Zero())
- return Success(0, E);
-
- // If Type & 1 is 0, the object in question is the complete object; reset to
- // a complete object designator in that case.
- //
- // If Type is 1 and we've lost track of the subobject, just find the complete
- // object instead. (If Type is 3, that's not correct behavior and we should
- // return 0 instead.)
- LValue End = Base;
- if (((Type & 1) == 0) || (End.Designator.Invalid && Type == 1)) {
- QualType T = getObjectType(End.getLValueBase());
- if (T.isNull())
- End.Designator.setInvalid();
- else {
- End.Designator = SubobjectDesignator(T);
- End.Offset = CharUnits::Zero();
- }
- }
-
- // FIXME: We should produce a valid object size for an unknown object with a
- // known designator, if Type & 1 is 1. For instance:
- //
- // extern struct X { char buff[32]; int a, b, c; } *p;
- // int a = __builtin_object_size(p->buff + 4, 3); // returns 28
- // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40
- //
- // This is GCC's behavior. We currently don't do this, but (hopefully) will in
- // the near future.
-
- // If it is not possible to determine which objects ptr points to at compile
- // time, __builtin_object_size should return (size_t) -1 for type 0 or 1
- // and (size_t) 0 for type 2 or 3.
- if (End.Designator.Invalid)
- return false;
-
- // According to the GCC documentation, we want the size of the subobject
- // denoted by the pointer. But that's not quite right -- what we actually
- // want is the size of the immediately-enclosing array, if there is one.
- int64_t AmountToAdd = 1;
- if (End.Designator.MostDerivedArraySize &&
- End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) {
- // We got a pointer to an array. Step to its end.
- AmountToAdd = End.Designator.MostDerivedArraySize -
- End.Designator.Entries.back().ArrayIndex;
- } else if (End.Designator.IsOnePastTheEnd) {
- // We're already pointing at the end of the object.
- AmountToAdd = 0;
+ if (!Base.getLValueBase()) {
+ // It is not possible to determine which objects ptr points to at compile time,
+ // __builtin_object_size should return (size_t) -1 for type 0 or 1
+ // and (size_t) 0 for type 2 or 3.
+ llvm::APSInt TypeIntVaue;
+ const Expr *ExprType = E->getArg(1);
+ if (!ExprType->EvaluateAsInt(TypeIntVaue, Info.Ctx))
+ return false;
+ if (TypeIntVaue == 0 || TypeIntVaue == 1)
+ return Success(-1, E);
+ if (TypeIntVaue == 2 || TypeIntVaue == 3)
+ return Success(0, E);
+ return Error(E);
}
- if (End.Designator.MostDerivedType->isIncompleteType() ||
- End.Designator.MostDerivedType->isFunctionType())
+ QualType T = GetObjectType(Base.getLValueBase());
+ if (T.isNull() ||
+ T->isIncompleteType() ||
+ T->isFunctionType() ||
+ T->isVariablyModifiedType() ||
+ T->isDependentType())
return Error(E);
- if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType,
- AmountToAdd))
- return false;
-
- auto EndOffset = End.getLValueOffset();
- if (BaseOffset > EndOffset)
- return Success(0, E);
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(T);
+ CharUnits Offset = Base.getLValueOffset();
- return Success(EndOffset - BaseOffset, E);
+ if (!Offset.isNegative() && Offset <= Size)
+ Size -= Offset;
+ else
+ Size = CharUnits::Zero();
+ return Success(Size, E);
}
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
@@ -6266,21 +6234,17 @@ bool IntExprEvaluator::VisitCallExpr(con
return ExprEvaluatorBaseTy::VisitCallExpr(E);
case Builtin::BI__builtin_object_size: {
- // The type was checked when we built the expression.
- unsigned Type =
- E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
- assert(Type <= 3 && "unexpected type");
-
- if (TryEvaluateBuiltinObjectSize(E, Type))
+ if (TryEvaluateBuiltinObjectSize(E))
return true;
// If evaluating the argument has side-effects, we can't determine the size
// of the object, and so we lower it to unknown now. CodeGen relies on us to
// handle all cases where the expression has side-effects.
- // Likewise, if Type is 3, we must handle this because CodeGen cannot give a
- // conservatively correct answer in that case.
- if (E->getArg(0)->HasSideEffects(Info.Ctx) || Type == 3)
- return Success((Type & 2) ? 0 : -1, E);
+ 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.
@@ -6290,12 +6254,10 @@ bool IntExprEvaluator::VisitCallExpr(con
case EvalInfo::EM_ConstantFold:
case EvalInfo::EM_EvaluateForOverflow:
case EvalInfo::EM_IgnoreSideEffects:
- // Leave it to IR generation.
return Error(E);
case EvalInfo::EM_ConstantExpressionUnevaluated:
case EvalInfo::EM_PotentialConstantExpressionUnevaluated:
- // Reduce it to a constant now.
- return Success((Type & 2) ? 0 : -1, E);
+ return Success(-1ULL, E);
}
}
Modified: cfe/trunk/test/CodeGen/object-size.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/object-size.c?rev=245342&r1=245341&r2=245342&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/object-size.c (original)
+++ cfe/trunk/test/CodeGen/object-size.c Tue Aug 18 15:32:55 2015
@@ -146,96 +146,3 @@ unsigned test18(int cond) {
// CHECK: call i64 @llvm.objectsize.i64
return __builtin_object_size(cond ? a : b, 0);
}
-
-// CHECK: @test19
-void test19() {
- struct {
- int a, b;
- } foo;
-
- // CHECK: store i32 8
- gi = __builtin_object_size(&foo.a, 0);
- // CHECK: store i32 4
- gi = __builtin_object_size(&foo.a, 1);
- // CHECK: store i32 8
- gi = __builtin_object_size(&foo.a, 2);
- // CHECK: store i32 4
- gi = __builtin_object_size(&foo.a, 3);
-}
-
-// CHECK: @test20
-void test20() {
- struct { int t[10]; } t[10];
-
- // CHECK: store i32 380
- gi = __builtin_object_size(&t[0].t[5], 0);
- // CHECK: store i32 20
- gi = __builtin_object_size(&t[0].t[5], 1);
- // CHECK: store i32 380
- gi = __builtin_object_size(&t[0].t[5], 2);
- // CHECK: store i32 20
- gi = __builtin_object_size(&t[0].t[5], 3);
-}
-
-// CHECK: @test21
-void test21() {
- struct { int t; } t;
-
- // CHECK: store i32 0
- gi = __builtin_object_size(&t + 1, 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t + 1, 1);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t + 1, 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t + 1, 3);
-
- // CHECK: store i32 0
- gi = __builtin_object_size(&t.t + 1, 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t.t + 1, 1);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t.t + 1, 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t.t + 1, 3);
-}
-
-// CHECK: @test22
-void test22() {
- struct { int t[10]; } t[10];
-
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[10], 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[10], 1);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[10], 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[10], 3);
-
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[9].t[10], 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[9].t[10], 1);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[9].t[10], 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(&t[9].t[10], 3);
-}
-
-struct Test23Ty { int t[10]; };
-
-// CHECK: @test23
-void test23(struct Test22Ty *p) {
- // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
- gi = __builtin_object_size(p, 0);
- // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
- gi = __builtin_object_size(p, 1);
- // CHECK:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
- gi = __builtin_object_size(p, 2);
-
- // Note: this is currently fixed at 0 because LLVM doesn't have sufficient
- // data to correctly handle type=3
- // CHECK: store i32 0
- gi = __builtin_object_size(p, 3);
-}
Modified: cfe/trunk/test/Sema/const-eval.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/const-eval.c?rev=245342&r1=245341&r2=245342&view=diff
==============================================================================
--- cfe/trunk/test/Sema/const-eval.c (original)
+++ cfe/trunk/test/Sema/const-eval.c Tue Aug 18 15:32:55 2015
@@ -118,6 +118,10 @@ float varfloat;
const float constfloat = 0;
EVAL_EXPR(43, varfloat && constfloat) // expected-error {{must have a constant size}}
+// <rdar://problem/11205586>
+// (Make sure we continue to reject this.)
+EVAL_EXPR(44, "x"[0]); // expected-error {{variable length array}}
+
// <rdar://problem/10962435>
EVAL_EXPR(45, ((char*)-1) + 1 == 0 ? 1 : -1)
EVAL_EXPR(46, ((char*)-1) + 1 < (char*) -1 ? 1 : -1)
More information about the cfe-commits
mailing list