[PATCH] D28427: Allow constexpr construction of subobjects unconditionally, not just in C++14.

David L. Jones via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 6 17:50:06 PST 2017


dlj created this revision.
dlj added a reviewer: rsmith.
dlj added subscribers: cfe-commits, EricWF.

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.)


https://reviews.llvm.org/D28427

Files:
  lib/AST/ExprConstant.cpp


Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -1627,8 +1627,17 @@
   // 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.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D28427.83476.patch
Type: text/x-patch
Size: 1134 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170107/a9218702/attachment.bin>


More information about the cfe-commits mailing list