From: Richard Smith Date: Sat, 29 Oct 2011 21:53:17 +0000 (+0000) Subject: constexpr evaluation: allow lvalue-to-rvalue conversion on any literal type, not X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b78c0b66481a59dbef7ac2a454e4f89448909749;p=clang constexpr evaluation: allow lvalue-to-rvalue conversion on any literal type, not 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 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 31fddb6248..e5bff359f8 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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(D); if (!VD || !(IsConstNonVolatile(VD->getType()) || isa(VD)) || - !(Type->isIntegralOrEnumerationType() || Type->isRealFloatingType()) || + !Type->isLiteralType() || !EvaluateVarDeclInit(Info, VD, LVal.CallIndex, RVal)) return false; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index b1ca20f4bc..57e6e2fce2 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -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}} + +}