aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-10-19 20:41:51 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-10-19 20:41:51 +0000
commite7d7c39be90bf654a8da0f53f6682d965426d081 (patch)
tree8b67471c9fd4dfe21130ecccfdacd847c65a4240
parent0d381810da19dd7677b9a79fca516d298fa5addb (diff)
-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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--lib/Sema/SemaDecl.cpp17
-rw-r--r--test/SemaCXX/cxx98-compat.cpp24
3 files changed, 39 insertions, 7 deletions
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<CXX98Compat>, 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}}
+ };
+ };
+}