diff options
author | David L. Jones <dlj@google.com> | 2017-01-09 21:38:07 +0000 |
---|---|---|
committer | David L. Jones <dlj@google.com> | 2017-01-09 21:38:07 +0000 |
commit | fb15aef140e7e832663b2c59cd50bb8958dee871 (patch) | |
tree | 7729bc0ec1a59c9cac2ff3b95e374a176166383f /lib/AST/ExprConstant.cpp | |
parent | 266cb72185242313c85a9f33dc33944da8b2b403 (diff) |
Allow constexpr construction of subobjects unconditionally, not just in C++14.
Summary:
Per https://wg21.link/CWG1677, the C++11 standard did not clarify that constant
initialization of an object allowed constexpr brace-or-equal initialization of
subobjects:
struct foo_t { union { int i; volatile int j; } u; };
__attribute__((__require_constant_initialization__))
static const foo_t x = {{0}};
Because foo_t::u has a volatile member, the initializer for x fails. However,
there is really no good reason, because this:
union foo_u { int i; volatile int j; };
__attribute__((__require_constant_initialization__))
static const foo_u x = {0};
does have a constant initializer.
(This was triggered by musl's pthread_mutex_t type when building under C++11.)
Reviewers: rsmith
Subscribers: EricWF, cfe-commits
Differential Revision: https://reviews.llvm.org/D28427
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291480 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index fe77c7f6f3..a8512b2940 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1627,8 +1627,17 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E, // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. - if (Info.getLangOpts().CPlusPlus14 && This && - Info.EvaluatingDecl == This->getLValueBase()) + // + // C++11 missed this detail for aggregates, so classes like this: + // struct foo_t { union { int i; volatile int j; } u; }; + // are not (obviously) initializable like so: + // __attribute__((__require_constant_initialization__)) + // static const foo_t x = {{0}}; + // because "i" is a subobject with non-literal initialization (due to the + // volatile member of the union). See: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 + // Therefore, we use the C++1y behavior. + if (This && Info.EvaluatingDecl == This->getLValueBase()) return true; // Prvalue constant expressions must be of literal types. |