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 63fa9a7..43cea51 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -559,21 +559,20 @@
}
// Handle (user-declared) destructors.
- if (isa<CXXDestructorDecl>(D)) {
+ if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(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 @@
// 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 @@
// 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 9385732..3ee1626 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2532,7 +2532,12 @@
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 @@
// 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 0000000..666e64b
--- /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;
+ };
+};