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) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits