Update constexpr implementation to match CWG's chosen approach for core issues
1358, 1360, 1452 and 1453.
- Instantiations of constexpr functions are always constexpr. This removes the
need for separate declaration/definition checking, which is now gone.
- This makes it possible for a constexpr function to be virtual, if they are
only dependently virtual. Virtual calls to such functions are not constant
expressions.
- Likewise, it's now possible for a literal type to have virtual base classes.
A constexpr constructor for such a type cannot actually produce a constant
expression, though, so add a special-case diagnostic for a constructor call
to such a type rather than trying to evaluate it.
- Classes with trivial default constructors (for which value initialization can
produce a fully-initialized value) are considered literal types.
- Classes with volatile members are not literal types.
- constexpr constructors can be members of non-literal types. We do not yet use
static initialization for global objects constructed in this way.
llvm-svn: 150359
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 2d4f4fb..a22d1e4 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -288,7 +288,7 @@
// 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 {{here}}
+ volatile const int vi = 1; // expected-note 2{{here}}
const int ci = 1;
volatile const int &vrci = ci;
static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
@@ -298,18 +298,23 @@
// - 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
// object, or
- struct S {
- constexpr S(int=0) : i(1), v(1) {}
- constexpr S(const S &s) : i(2), v(2) {}
- int i;
- volatile int v; // expected-note {{here}}
+ struct V {
+ constexpr V() : v(1) {}
+ volatile int v; // expected-note {{not literal because}}
};
- constexpr S s;
+ constexpr V v; // expected-error {{non-literal type}}
+ struct S {
+ constexpr S(int=0) : i(1), v(const_cast<volatile int&>(vi)) {}
+ constexpr S(const S &s) : i(2), v(const_cast<volatile int&>(vi)) {}
+ int i;
+ volatile int &v;
+ };
+ constexpr S s; // ok
constexpr volatile S vs; // expected-note {{here}}
- constexpr const volatile S &vrs = s;
+ constexpr const volatile S &vrs = s; // ok
static_assert(s.i, "");
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(const_cast<int&>(s.v), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}}
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, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}