summaryrefslogtreecommitdiffstats
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorDavid L. Jones <dlj@google.com>2017-01-09 21:38:07 +0000
committerDavid L. Jones <dlj@google.com>2017-01-09 21:38:07 +0000
commitfb15aef140e7e832663b2c59cd50bb8958dee871 (patch)
tree7729bc0ec1a59c9cac2ff3b95e374a176166383f /lib/AST/ExprConstant.cpp
parent266cb72185242313c85a9f33dc33944da8b2b403 (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.cpp13
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.