]> granicus.if.org Git - clang/commitdiff
Implement the new C++0x rules for non-trivial things in unions so that
authorSean Hunt <scshunt@csclub.uwaterloo.ca>
Mon, 16 May 2011 22:41:40 +0000 (22:41 +0000)
committerSean Hunt <scshunt@csclub.uwaterloo.ca>
Mon, 16 May 2011 22:41:40 +0000 (22:41 +0000)
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

lib/AST/DeclCXX.cpp
lib/Sema/SemaDecl.cpp
test/SemaCXX/cxx0x-nontrivial-union.cpp [new file with mode: 0644]

index 63fa9a77af0c63bb36b78aae700a58d441e04a9b..43cea51e93c34ad4b957ee7b134618aa0f6359ec 100644 (file)
@@ -559,21 +559,20 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 
   // 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 @@ 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;
       }
     }
 
index 93857324a1f340ae13a18d28a53e32ab8ccbfdee..3ee1626f7e0d0bc74ecc57e06f72f2c1e5a7d6f2 100644 (file)
@@ -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 (file)
index 0000000..666e64b
--- /dev/null
@@ -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;
+  };
+};