diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f84c6347cb0a..bb7042d1954d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1560,7 +1560,8 @@ static bool AreElementsOfSameArray(QualType ObjType, /// \param Info - Information about the ongoing evaluation. /// \param Conv - The expression for which we are performing the conversion. /// Used for diagnostics. -/// \param Type - The type we expect this conversion to produce. +/// \param Type - The type we expect this conversion to produce, before +/// stripping cv-qualifiers in the case of a non-clas type. /// \param LVal - The glvalue on which we are attempting to perform this action. /// \param RVal - The produced value will be placed here. static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, @@ -2536,7 +2537,9 @@ public: if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) return false; CCValue RVal; - if (!HandleLValueToRValueConversion(Info, E, E->getType(), LVal, RVal)) + // Note, we use the subexpression's type in order to retain cv-qualifiers. + if (!HandleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), + LVal, RVal)) return false; return DerivedSuccess(RVal, E); } diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index ac759cb356db..6c7a4947d783 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -268,14 +268,12 @@ namespace LValueToRValue { // non-volatile const object with a preceding initialization, initialized // with a constant expression [Note: a string literal (2.14.5 [lex.string]) // corresponds to an array of such objects. -end note], or - volatile const int vi = 1; // expected-note 2{{here}} + volatile const int vi = 1; // expected-note {{here}} const int ci = 1; volatile const int &vrci = ci; - static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} static_assert(const_cast(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} - static_assert(vrci, ""); // ok, vrci is converted to a prvalue before - // evaluation and loses its volatility in the - // conversion. + static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} // - a non-volatile glvalue of literal type that refers to a non-volatile // object defined with constexpr, or that refers to a sub-object of such an @@ -287,13 +285,14 @@ namespace LValueToRValue { volatile int v; // expected-note {{here}} }; constexpr S s; - constexpr volatile S vs; // expected-note 2{{here}} + constexpr volatile S vs; // expected-note {{here}} constexpr const volatile S &vrs = s; static_assert(s.i, ""); - static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile member 'v'}} - static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}} + static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast(s.v), ""); // expected-error {{constant expression}} expected-note {{read of volatile member 'v'}} + static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} static_assert(const_cast(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}} - static_assert(vrs.i, ""); // ok + static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} // - a non-volatile glvalue of literal type that refers to a non-volatile // temporary object whose lifetime has not ended, initialized with a diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 36736ad297c3..763c41680ce6 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1011,17 +1011,23 @@ volatile constexpr int n1 = 0; // expected-note {{here}} volatile const int n2 = 0; // expected-note {{here}} int n3 = 37; // expected-note {{declared here}} -constexpr int m1 = n1; // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}} -constexpr int m2 = n2; // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}} +constexpr int m1 = n1; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} +constexpr int m2 = n2; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} +constexpr int m1b = const_cast(n1); // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}} +constexpr int m2b = const_cast(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}} struct T { int n; }; const T t = { 42 }; // expected-note {{declared here}} constexpr int f(volatile int &&r) { - return r; // expected-note {{read of volatile temporary is not allowed in a constant expression}} + return r; // expected-note {{read of volatile-qualified type 'volatile int'}} +} +constexpr int g(volatile int &&r) { + return const_cast(r); // expected-note {{read of volatile temporary is not allowed in a constant expression}} } struct S { - int k : f(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'f(0)'}} + 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-error {{constant expression}} expected-note {{read of non-constexpr variable}} };