]> granicus.if.org Git - clang/commitdiff
constexpr evaluation: allow lvalue-to-rvalue conversion on any literal type, not
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 29 Oct 2011 21:53:17 +0000 (21:53 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 29 Oct 2011 21:53:17 +0000 (21:53 +0000)
just integers and floating point types. Since we don't support evaluating class
types or performing lvalue-to-rvalue conversions on array elements yet, this
just means pointer types right now.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143298 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 31fddb62485923458b160dc65af2bbfbba44d6ee..e5bff359f8504d847015f4a85832396504d82d41 100644 (file)
@@ -457,9 +457,6 @@ bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
     // parameters are constant expressions even if they're non-const.
     // In C, such things can also be folded, although they are not ICEs.
     //
-    // FIXME: Allow folding any const variable of literal type initialized with
-    // a constant expression. For now, we only allow variables with integral and
-    // floating types to be folded.
     // FIXME: volatile-qualified ParmVarDecls need special handling. A literal
     // interpretation of C++11 suggests that volatile parameters are OK if
     // they're never read (there's no prohibition against constructing volatile
@@ -467,7 +464,7 @@ bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
     // them are not permitted.
     const VarDecl *VD = dyn_cast<VarDecl>(D);
     if (!VD || !(IsConstNonVolatile(VD->getType()) || isa<ParmVarDecl>(VD)) ||
-        !(Type->isIntegralOrEnumerationType() || Type->isRealFloatingType()) ||
+        !Type->isLiteralType() ||
         !EvaluateVarDeclInit(Info, VD, LVal.CallIndex, RVal))
       return false;
 
index b1ca20f4bcaeb94429572a77c75363eab96ae4a5..57e6e2fce26ec0c93d11e3052ad1b7f8d5dd7f78 100644 (file)
@@ -119,3 +119,41 @@ namespace ParameterScopes {
   using check_value = int[9];
 
 }
+
+namespace Pointers {
+
+  constexpr int f(int n, const int *a, const int *b, const int *c) {
+    return n == 0 ? 0 : *a + f(n-1, b, c, a);
+  }
+
+  const int x = 1, y = 10, z = 100;
+  constexpr int n1 = f(23, &x, &y, &z);
+  // FIXME: this isn't an ICE yet.
+  using check_value_1 = int[n1];
+  using check_value_1 = int[788];
+
+  constexpr int g(int n, int a, int b, int c) {
+    return f(n, &a, &b, &c);
+  }
+  constexpr int n2 = g(23, x, y, z);
+  using check_value_1 = int[n2];
+
+}
+
+namespace FunctionPointers {
+
+  constexpr int Double(int n) { return 2 * n; }
+  constexpr int Triple(int n) { return 3 * n; }
+  constexpr int Twice(int (*F)(int), int n) { return F(F(n)); }
+  constexpr int Quadruple(int n) { return Twice(Double, n); }
+  constexpr auto Select(int n) -> int (*)(int) {
+    return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;
+  }
+  constexpr int Apply(int (*F)(int), int n) { return F(n); }
+
+  using check_value = int[1 + Apply(Select(4), 5) + Apply(Select(3), 7)];
+  using check_value = int[42];
+
+  constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}}
+
+}