[PATCH] D35190: __builtin_constant_p should consider the parameter of a constexpr function as constant

Olivier Goffart via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 10 01:00:45 PDT 2017


ogoffart created this revision.

This allows to do something like:

  
  constexpr int func(int x) {
    return __builtin_constant_p(x) ? compute_constexpr(x) : compute_runtime(x);
  }


This kind of code is accepted by GCC since GCC 4.8.

      

The problem was that EvaluateBuiltinConstantP was discarding the EvalInfo and its frames. So just keep the EvalInfo


https://reviews.llvm.org/D35190

Files:
  lib/AST/ExprConstant.cpp
  test/SemaCXX/constant-expression-cxx11.cpp
  test/SemaCXX/constant-expression-cxx1y.cpp


Index: test/SemaCXX/constant-expression-cxx1y.cpp
===================================================================
--- test/SemaCXX/constant-expression-cxx1y.cpp
+++ test/SemaCXX/constant-expression-cxx1y.cpp
@@ -982,3 +982,8 @@
   int *p = &n;
   p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
 }
+
+namespace BuiltinConstantP {
+  constexpr int f1(int i) { return __builtin_constant_p(i += 4) ? 0 : i += 3; }
+  static_assert(f1(10) == 13, "");
+}
Index: test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2169,3 +2169,13 @@
   constexpr int *q = (&n + 1) - (unsigned __int128)-1; // expected-error {{constant expression}} expected-note {{cannot refer to element -3402}}
   constexpr int *r = &(&n + 1)[(unsigned __int128)-1]; // expected-error {{constant expression}} expected-note {{cannot refer to element 3402}}
 }
+
+namespace BuiltinConstantP {
+  int computeRuntime(int);
+  constexpr int compute(int x) {
+    return __builtin_constant_p(x) ? x + 2 : computeRuntime(x);
+  }
+  constexpr int x = compute(25);
+  int n; // expected-note{{declared here}}
+  constexpr int z = compute(n); // expected-error {{constant expression}} expected-note{{non-const variable}}
+}
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -7203,7 +7203,7 @@
 
 /// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to
 /// GCC as we can manage.
-static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) {
+static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
   QualType ArgType = Arg->getType();
 
   // __builtin_constant_p always has one operand. The rules which gcc follows
@@ -7219,25 +7219,24 @@
   //
   // FIXME: GCC also intends to return 1 for literals of aggregate types, but
   // its support for this does not currently work.
-  if (ArgType->isIntegralOrEnumerationType()) {
-    Expr::EvalResult Result;
-    if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects)
+  SpeculativeEvaluationRAII SpeculativeEval(Info);
+  FoldConstant Fold(Info, true);
+  if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() ||
+      ArgType->isAnyComplexType()) {
+    APValue V;
+    if (!EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects)
       return false;
-
-    APValue &V = Result.Val;
-    if (V.getKind() == APValue::Int)
+    if (V.getKind() == APValue::Int || V.getKind() == APValue::Float ||
+        V.getKind() == APValue::ComplexInt ||
+        V.getKind() == APValue::ComplexFloat)
       return true;
     if (V.getKind() == APValue::LValue)
       return EvaluateBuiltinConstantPForLValue(V);
-  } 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)
+        !Info.EvalStatus.HasSideEffects)
       return EvaluateBuiltinConstantPForLValue(LV);
   }
 
@@ -7628,7 +7627,7 @@
   }
 
   case Builtin::BI__builtin_constant_p:
-    return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E);
+    return Success(EvaluateBuiltinConstantP(Info, E->getArg(0)), E);
 
   case Builtin::BI__builtin_ctz:
   case Builtin::BI__builtin_ctzl:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D35190.105817.patch
Type: text/x-patch
Size: 3787 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170710/6ee92359/attachment.bin>


More information about the cfe-commits mailing list