From 4d59eebb49082306d2d9a53b5aa1ea3443fdd3c2 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 9 Feb 2012 06:40:58 +0000 Subject: [PATCH] DR1359: A constexpr constructor does not need to initialize an empty struct or empty union. This still rejects anonymous member structs or unions which only contain such empty class types, pending standard wording defining exactly what an empty class type is. llvm-svn: 150157 --- clang/lib/Sema/SemaDeclCXX.cpp | 17 ++++++++++++----- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 10 ++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 62332b8b4aaa..8ba84fe86a50 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -815,7 +815,11 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, bool &Diagnosed) { if (Field->isUnnamedBitfield()) return; - + + if (Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->isEmpty()) + return; + if (!Inits.count(Field)) { if (!Diagnosed) { SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init); @@ -901,11 +905,14 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body, if (const CXXConstructorDecl *Constructor = dyn_cast(Dcl)) { const CXXRecordDecl *RD = Constructor->getParent(); - // - every non-static data member and base class sub-object shall be - // initialized; + // DR1359: + // - every non-variant non-static data member and base class sub-object + // shall be initialized; + // - if the class is a non-empty union, or for each non-empty anonymous + // union member of a non-union class, exactly one non-static data member + // shall be initialized; if (RD->isUnion()) { - // DR1359: Exactly one member of a union shall be initialized. - if (Constructor->getNumCtorInitializers() == 0) { + if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) { Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init); return false; } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index abd5292ada71..86b7ded95950 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -151,6 +151,16 @@ struct AnonMembers { constexpr AnonMembers(int(&)[6]) {} // expected-error {{constexpr constructor must initialize all members}} }; +union Empty { + constexpr Empty() {} // ok +} constexpr empty1; + +struct EmptyVariant { + union {}; + struct {}; + constexpr EmptyVariant() {} // ok +} constexpr empty2; + template using Int = int; template struct TemplateInit {