diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-05 01:23:16 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-05 01:23:16 +0000 |
commit | 9ec7197796a2730d54ae7f632553b5311b2ba3b5 (patch) | |
tree | b63349457a064e85022334ba47052ff34fb6f74c | |
parent | eac1f6746a2915fea3ed42284b07e274c0095a95 (diff) |
constexpr: Fix implementation of DR1311: check for volatile qualifiers in
lvalue-to-rvalue conversions on the source type of the conversion, not the
target type (which has them removed for non-class types).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149796 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/ExprConstant.cpp | 7 | ||||
-rw-r--r-- | test/CXX/expr/expr.const/p2-0x.cpp | 17 | ||||
-rw-r--r-- | test/SemaCXX/constant-expression-cxx11.cpp | 14 |
3 files changed, 23 insertions, 15 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index f84c6347cb..bb7042d195 100644 --- a/lib/AST/ExprConstant.cpp +++ b/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/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index ac759cb356..6c7a4947d7 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/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<int&>(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<int&>(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<int&>(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/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 36736ad297..763c41680c 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/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<const int&>(n1); // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}} +constexpr int m2b = const_cast<const int&>(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<int&>(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}} }; |