From: Richard Smith Date: Wed, 19 Oct 2011 20:41:51 +0000 (+0000) Subject: -Wc++98-compat: warn on nontrivial types used in unions and anonymous structs. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7d7c39be90bf654a8da0f53f6682d965426d081;p=clang -Wc++98-compat: warn on nontrivial types used in unions and anonymous structs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142541 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 6823fb0d17..8c70572a74 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -897,6 +897,11 @@ def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " "%select{constructor|copy constructor|move constructor|copy assignment " "operator|move assignment operator|destructor}2">; +def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning< + "%select{anonymous struct|union}0 member %1 with a non-trivial " + "%select{constructor|copy constructor|move constructor|copy assignment " + "operator|move assignment operator|destructor}2 is incompatible with C++98">, + InGroup, DefaultIgnore; def note_nontrivial_has_virtual : Note< "because type %0 has a virtual %select{member function|base class}1">; def note_nontrivial_has_nontrivial : Note< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8cadec5f89..7dafc50b3d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2711,7 +2711,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // 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)) + if (CheckNontrivialField(FD)) Invalid = true; } else if ((*Mem)->isImplicit()) { // Any implicit members are fine. @@ -8558,7 +8558,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. - if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(NewFD)) + if (CheckNontrivialField(NewFD)) NewFD->setInvalidDecl(); } } @@ -8617,7 +8617,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { member = CXXDestructor; if (member != CXXInvalid) { - if (getLangOptions().ObjCAutoRefCount && RDecl->hasObjectMember()) { + if (!getLangOptions().CPlusPlus0x && + getLangOptions().ObjCAutoRefCount && RDecl->hasObjectMember()) { // Objective-C++ ARC: it is an error to have a non-trivial field of // a union. However, system headers in Objective-C programs // occasionally have Objective-C lifetime objects within unions, @@ -8631,11 +8632,13 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; } } - - Diag(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member) - << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; + + Diag(FD->getLocation(), getLangOptions().CPlusPlus0x ? + diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : + diag::err_illegal_union_or_anon_struct_member) + << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; DiagnoseNontrivial(RT, member); - return true; + return !getLangOptions().CPlusPlus0x; } } } diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index ddcc1efe5a..6d3abe8537 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -213,3 +213,27 @@ namespace CopyCtorIssues { const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}} const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}} } + +namespace UnionOrAnonStructMembers { + struct NonTrivCtor { + NonTrivCtor(); // expected-note 2{{user-declared constructor}} + }; + struct NonTrivCopy { + NonTrivCopy(const NonTrivCopy&); // expected-note 2{{user-declared copy constructor}} + }; + struct NonTrivDtor { + ~NonTrivDtor(); // expected-note 2{{user-declared destructor}} + }; + union BadUnion { + NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial constructor is incompatible with C++98}} + NonTrivCopy ntcp; // expected-warning {{union member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} + NonTrivDtor ntd; // expected-warning {{union member 'ntd' with a non-trivial destructor is incompatible with C++98}} + }; + struct Wrap { + struct { + NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial constructor is incompatible with C++98}} + NonTrivCopy ntcp; // expected-warning {{anonymous struct member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} + NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}} + }; + }; +}