]> granicus.if.org Git - clang/commitdiff
Revert Fix interactions between __builtin_constant_p and constexpr to match current...
authorJorge Gorbe Moya <jgorbe@google.com>
Sat, 27 Apr 2019 00:32:04 +0000 (00:32 +0000)
committerJorge Gorbe Moya <jgorbe@google.com>
Sat, 27 Apr 2019 00:32:04 +0000 (00:32 +0000)
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
lib/Sema/SemaChecking.cpp
test/SemaCXX/builtin-constant-p.cpp [deleted file]
test/SemaCXX/enable_if.cpp

index 0a8b60d70de4fdd89988904b1988c69520f12bd4..a30e83c632827d90bf757a737ab437d2834f6f69 100644 (file)
@@ -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<const Expr *>()) {
-    if (!isa<StringLiteral>(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<typename LValue>
+static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) {
+  const Expr *E = LV.getLValueBase().template dyn_cast<const Expr*>();
+  return E && isa<StringLiteral>(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) &&
index 4c2d1dc768d958d25b03b6297f2828775ceb9647..de061e62aad5496b9a8d36311fd553254b43b84b 100644 (file)
@@ -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 (file)
index 252c7bb..0000000
+++ /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<typename T> constexpr bool bcp(T t) {
-  return __builtin_constant_p(t);
-}
-template<typename T> 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<int*>(nullptr));
-static_assert(bcp_fold<int*>(nullptr));
-static_assert(bcp<const char*>(nullptr));
-static_assert(bcp_fold<const char*>(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
index fd1375136a2ec481d97965a0ae35b5c6d16fee37..4bc974dafc289ecf1416d06ff1413bef9151e7ff 100644 (file)
@@ -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}}
-  }
-}
-