diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 2caaaab9ef2869707e1b8bc8ec6187263037bd8c..b3f8925b64643ae6552592ac2134e3b1f34a6b5a 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2903,7 +2903,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, // All the remaining cases only permit reading. Info.FFDiag(E, diag::note_constexpr_modify_global); return CompleteObject(); - } else if (VD->isConstexpr() || BaseType.isConstQualified()) { + } else if (VD->isConstexpr()) { // OK, we can read this variable. } else if (BaseType->isIntegralOrEnumerationType()) { // In OpenCL if a variable is in constant address space it is a const value. @@ -2928,6 +2928,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } else { Info.CCEDiag(E); } + } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) { + Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD; + // Keep evaluating to see what we can do. } else { // FIXME: Allow folding of values of any literal type in all languages. if (Info.checkingPotentialConstantExpression() && diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 9ec8318b9e02d0f07885bf982dcb7867c959ff1e..581a524339e752326005e91fe31a88497bd1d517 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1195,7 +1195,7 @@ struct S { int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}} int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}} int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}} - int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}} + int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}} expected-warning{{expression is not an integral constant expression}} expected-note{{read of non-constexpr variable 't' is not allowed}} }; } diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp index 0a1877cc8c31f63d904900421c3d2fa9bd2e4a80..dfdf50ad54849dcd3e926f4b2c87451047c7c15c 100644 --- a/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/test/SemaCXX/constant-expression-cxx1y.cpp @@ -959,18 +959,21 @@ namespace PR27989 { } namespace const_char { -template <int M, int N> +template <int N> constexpr int sum(const char (&Arr)[N]) { - static_assert(N >= M, ""); int S = 0; - for (unsigned I = 0; I != M; ++I) - S += Arr[I]; + for (unsigned I = 0; I != N; ++I) + S += Arr[I]; // expected-note 2{{read of non-constexpr variable 'Cs' is not allowed}} return S; } // As an extension, we support evaluating some things that are `const` as though -// they were `constexpr`. -const char Cs[] = {'a', 'b', 'c'}; -const int N = 2; -static_assert(sum<N>(Cs) == 'a' + 'b', ""); +// they were `constexpr` when folding, but it should not be allowed in normal +// constexpr evaluation. +const char Cs[] = {'a', 'b'}; +void foo() __attribute__((enable_if(sum(Cs) == 'a' + 'b', ""))); +void run() { foo(); } + +static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral constant expression}} expected-note{{in call to 'sum(Cs)'}} +constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}} }