From: Sean Hunt Date: Mon, 16 May 2011 22:41:40 +0000 (+0000) Subject: Implement the new C++0x rules for non-trivial things in unions so that X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cf34e757b968f1fa7965cab1464212ade4d9f991;p=clang Implement the new C++0x rules for non-trivial things in unions so that my defaulted constructor tests stop yelling at me about them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131432 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 63fa9a77af..43cea51e93 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -559,21 +559,20 @@ void CXXRecordDecl::addedMember(Decl *D) { } // Handle (user-declared) destructors. - if (isa(D)) { + if (CXXDestructorDecl *DD = dyn_cast(D)) { data().DeclaredDestructor = true; data().UserDeclaredDestructor = true; // C++ [class]p4: // A POD-struct is an aggregate class that has [...] no user-defined // destructor. + // This bit is the C++03 POD bit, not the 0x one. data().PlainOldData = false; - // C++ [class.dtor]p3: - // A destructor is trivial if it is an implicitly-declared destructor and - // [...]. - // - // FIXME: C++0x: don't do this for "= default" destructors - data().HasTrivialDestructor = false; + // C++0x [class.dtor]p5: + // A destructor is trivial if it is not user-provided and [...] + if (DD->isUserProvided()) + data().HasTrivialDestructor = false; return; } @@ -611,9 +610,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // C++ [class]p4: // A POD-struct is an aggregate class that [...] has no user-defined // copy assignment operator [...]. - // FIXME: This should be probably determined dynamically in terms of - // other more precise attributes to correctly model how it is specified - // in C++0x. Setting it here happens to do the right thing. + // This is the C++03 bit only. data().PlainOldData = false; if (!isRValueRefArg) { @@ -626,16 +623,16 @@ void CXXRecordDecl::addedMember(Decl *D) { // C++0x [class.copy]p27: // A copy/move assignment operator for class X is trivial if it is // neither user-provided nor deleted [...] - // FIXME: C++0x: don't do this for "= default" copy operators. - data().HasTrivialCopyAssignment = false; + if (Method->isUserProvided()) + data().HasTrivialCopyAssignment = false; } else { // This is a move assignment operator. // C++0x [class.copy]p27: // A copy/move assignment operator for class X is trivial if it is // neither user-provided nor deleted [...] - // FIXME: C++0x: don't do this for "= default" copy operators. - data().HasTrivialMoveAssignment = false; + if (Method->isUserProvided()) + data().HasTrivialMoveAssignment = false; } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 93857324a1..3ee1626f7e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2532,7 +2532,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; } - if (CheckNontrivialField(FD)) + // C++ [class.union]p1 + // An object of a class with a non-trivial constructor, a non-trivial + // copy constructor, a non-trivial destructor, or a non-trivial copy + // assignment operator cannot be a member of a union, nor can an + // array of such objects. + if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(FD)) Invalid = true; } else if ((*Mem)->isImplicit()) { // Any implicit members are fine. @@ -7612,8 +7617,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // destructor, or a non-trivial copy assignment operator // cannot be a member of a union, nor can an array of such // objects. - // TODO: C++0x alters this restriction significantly. - if (CheckNontrivialField(NewFD)) + if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(NewFD)) NewFD->setInvalidDecl(); } } diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp new file mode 100644 index 0000000000..666e64be66 --- /dev/null +++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct non_trivial { + non_trivial(); + non_trivial(const non_trivial&); + non_trivial& operator = (const non_trivial&); + ~non_trivial(); +}; + +union u { + non_trivial nt; +}; + +union bad { + static int i; // expected-error {{static data member}} +}; + +struct s { + union { + non_trivial nt; + }; +};