From 2b5f7f9e2e42cca4f8df5763cd2529324a2d421a Mon Sep 17 00:00:00 2001 From: Jorge Gorbe Moya Date: Sat, 27 Apr 2019 00:32:04 +0000 Subject: [PATCH] Revert Fix interactions between __builtin_constant_p and constexpr to match current trunk GCC. This reverts r359059 (git commit 0b098754b73f3b96d00ecb1c7605760b11c90298) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359361 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 63 +++++++++++++---------------- lib/Sema/SemaChecking.cpp | 6 +-- test/SemaCXX/builtin-constant-p.cpp | 61 ---------------------------- test/SemaCXX/enable_if.cpp | 11 ----- 4 files changed, 29 insertions(+), 112 deletions(-) delete mode 100644 test/SemaCXX/builtin-constant-p.cpp diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 0a8b60d70d..a30e83c632 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -7801,33 +7801,19 @@ EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) { } /// EvaluateBuiltinConstantPForLValue - Determine the result of -/// __builtin_constant_p when applied to the given pointer. +/// __builtin_constant_p when applied to the given lvalue. /// -/// A pointer is only "constant" if it is null (or a pointer cast to integer) -/// or it points to the first character of a string literal. -static bool EvaluateBuiltinConstantPForLValue(const APValue &LV) { - APValue::LValueBase Base = LV.getLValueBase(); - if (Base.isNull()) { - // A null base is acceptable. - return true; - } else if (const Expr *E = Base.dyn_cast()) { - if (!isa(E)) - return false; - return LV.getLValueOffset().isZero(); - } else { - // Any other base is not constant enough for GCC. - return false; - } +/// An lvalue is only "constant" if it is a pointer or reference to the first +/// character of a string literal. +template +static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) { + const Expr *E = LV.getLValueBase().template dyn_cast(); + return E && isa(E) && LV.getLValueOffset().isZero(); } /// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to /// GCC as we can manage. -static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) { - // Constant-folding is always enabled for the operand of __builtin_constant_p - // (even when the enclosing evaluation context otherwise requires a strict - // language-specific constant expression). - FoldConstant Fold(Info, true); - +static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { QualType ArgType = Arg->getType(); // __builtin_constant_p always has one operand. The rules which gcc follows @@ -7835,27 +7821,34 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) { // // - If the operand is of integral, floating, complex or enumeration type, // and can be folded to a known value of that type, it returns 1. - // - If the operand can be folded to a pointer to the first character - // of a string literal (or such a pointer cast to an integral type) - // or to a null pointer or an integer cast to a pointer, it returns 1. + // - If the operand and can be folded to a pointer to the first character + // of a string literal (or such a pointer cast to an integral type), it + // returns 1. // // Otherwise, it returns 0. // // FIXME: GCC also intends to return 1 for literals of aggregate types, but // its support for this does not currently work. - if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() || - ArgType->isAnyComplexType() || ArgType->isPointerType() || - ArgType->isNullPtrType()) { - APValue V; - if (!::EvaluateAsRValue(Info, Arg, V)) + if (ArgType->isIntegralOrEnumerationType()) { + Expr::EvalResult Result; + if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects) return false; - // For a pointer (possibly cast to integer), there are special rules. + APValue &V = Result.Val; + if (V.getKind() == APValue::Int) + return true; if (V.getKind() == APValue::LValue) return EvaluateBuiltinConstantPForLValue(V); - - // Otherwise, any constant value is good enough. - return V.getKind() != APValue::Uninitialized; + } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) { + return Arg->isEvaluatable(Ctx); + } else if (ArgType->isPointerType() || Arg->isGLValue()) { + LValue LV; + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info) + : EvaluatePointer(Arg, LV, Info)) && + !Status.HasSideEffects) + return EvaluateBuiltinConstantPForLValue(LV); } // Anything else isn't considered to be sufficiently constant. @@ -8266,7 +8259,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_constant_p: { auto Arg = E->getArg(0); - if (EvaluateBuiltinConstantP(Info, Arg)) + if (EvaluateBuiltinConstantP(Info.Ctx, Arg)) return Success(true, E); auto ArgTy = Arg->IgnoreImplicit()->getType(); if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) && diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 4c2d1dc768..de061e62aa 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1199,14 +1199,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (checkArgCount(*this, TheCall, 1)) return true; TheCall->setType(Context.IntTy); break; - case Builtin::BI__builtin_constant_p: { + case Builtin::BI__builtin_constant_p: if (checkArgCount(*this, TheCall, 1)) return true; - ExprResult Arg = DefaultFunctionArrayLvalueConversion(TheCall->getArg(0)); - if (Arg.isInvalid()) return true; - TheCall->setArg(0, Arg.get()); TheCall->setType(Context.IntTy); break; - } case Builtin::BI__builtin_launder: return SemaBuiltinLaunder(*this, TheCall); case Builtin::BI__sync_fetch_and_add: diff --git a/test/SemaCXX/builtin-constant-p.cpp b/test/SemaCXX/builtin-constant-p.cpp deleted file mode 100644 index 252c7bbac5..0000000000 --- a/test/SemaCXX/builtin-constant-p.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// RUN: %clang_cc1 -std=c++17 -verify %s - -using intptr_t = __INTPTR_TYPE__; - -// Test interaction of constexpr and __builtin_constant_p. - -template constexpr bool bcp(T t) { - return __builtin_constant_p(t); -} -template constexpr bool bcp_fold(T t) { - return __builtin_constant_p(((void)(intptr_t)&t, t)); -} - -constexpr intptr_t ensure_fold_is_generally_not_enabled = // expected-error {{constant expression}} - (intptr_t)&ensure_fold_is_generally_not_enabled; // expected-note {{cast}} - -constexpr intptr_t ptr_to_int(const void *p) { - return __builtin_constant_p(1) ? (intptr_t)p : (intptr_t)p; -} - -constexpr int *int_to_ptr(intptr_t n) { - return __builtin_constant_p(1) ? (int*)n : (int*)n; -} - -int x; - -// Integer and floating point constants encountered during constant expression -// evaluation are considered constant. So is nullptr_t. -static_assert(bcp(1)); -static_assert(bcp_fold(1)); -static_assert(bcp(1.0)); -static_assert(bcp_fold(1.0)); -static_assert(bcp(nullptr)); -static_assert(bcp_fold(nullptr)); - -// Pointers to the start of strings are considered constant. -static_assert(bcp("foo")); -static_assert(bcp_fold("foo")); - -// Null pointers are considered constant. -static_assert(bcp(nullptr)); -static_assert(bcp_fold(nullptr)); -static_assert(bcp(nullptr)); -static_assert(bcp_fold(nullptr)); - -// Other pointers are not. -static_assert(!bcp(&x)); -static_assert(!bcp_fold(&x)); - -// Pointers cast to integers follow the rules for pointers. -static_assert(bcp(ptr_to_int("foo"))); -static_assert(bcp_fold(ptr_to_int("foo"))); -static_assert(!bcp(ptr_to_int(&x))); -static_assert(!bcp_fold(ptr_to_int(&x))); - -// Integers cast to pointers follow the integer rules. -static_assert(bcp(int_to_ptr(0))); -static_assert(bcp_fold(int_to_ptr(0))); -static_assert(bcp(int_to_ptr(123))); // GCC rejects these due to not recognizing -static_assert(bcp_fold(int_to_ptr(123))); // the bcp conditional in 'int_to_ptr' ... -static_assert(__builtin_constant_p((int*)123)); // ... but GCC accepts this diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp index fd1375136a..4bc974dafc 100644 --- a/test/SemaCXX/enable_if.cpp +++ b/test/SemaCXX/enable_if.cpp @@ -522,14 +522,3 @@ void test() { InConstantContext::foo("abc"); } } // namespace InConstantContext - -namespace StringLiteralDetector { - void need_string_literal(const char *p) __attribute__((enable_if(__builtin_constant_p(p), "argument is not a string literal"))); // expected-note 2{{not a string literal}} - void test(const char *unknown) { - need_string_literal("foo"); - need_string_literal(unknown); // expected-error {{no matching function}} - constexpr char str[] = "bar"; - need_string_literal(str); // expected-error {{no matching function}} - } -} - -- 2.40.0