]> granicus.if.org Git - clang/commitdiff
Implement some tests for defaulted constructors. To do this I had to
authorSean Hunt <scshunt@csclub.uwaterloo.ca>
Tue, 17 May 2011 00:19:05 +0000 (00:19 +0000)
committerSean Hunt <scshunt@csclub.uwaterloo.ca>
Tue, 17 May 2011 00:19:05 +0000 (00:19 +0000)
suppress an error we were previously emitting on valid union code.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131440 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/cxx0x-defaulted-functions.cpp [new file with mode: 0644]
test/SemaCXX/cxx0x-deleted-default-ctor.cpp [new file with mode: 0644]
test/SemaCXX/default-constructor-initializers.cpp

index c9dddfe5c6ebf6de87c71e2258a832487c3d63e0..e280972f023f8dfd5d6010798302e1418f8329c7 100644 (file)
@@ -2017,24 +2017,26 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
     return false;
   }
 
-  if (FieldBaseElementType->isReferenceType()) {
-    SemaRef.Diag(Constructor->getLocation(), 
-                 diag::err_uninitialized_member_in_ctor)
-    << (int)Constructor->isImplicit() 
-    << SemaRef.Context.getTagDeclType(Constructor->getParent())
-    << 0 << Field->getDeclName();
-    SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
-    return true;
-  }
+  if (!Field->getParent()->isUnion()) {
+    if (FieldBaseElementType->isReferenceType()) {
+      SemaRef.Diag(Constructor->getLocation(), 
+                   diag::err_uninitialized_member_in_ctor)
+      << (int)Constructor->isImplicit() 
+      << SemaRef.Context.getTagDeclType(Constructor->getParent())
+      << 0 << Field->getDeclName();
+      SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
+      return true;
+    }
 
-  if (FieldBaseElementType.isConstQualified()) {
-    SemaRef.Diag(Constructor->getLocation(), 
-                 diag::err_uninitialized_member_in_ctor)
-    << (int)Constructor->isImplicit() 
-    << SemaRef.Context.getTagDeclType(Constructor->getParent())
-    << 1 << Field->getDeclName();
-    SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
-    return true;
+    if (FieldBaseElementType.isConstQualified()) {
+      SemaRef.Diag(Constructor->getLocation(), 
+                   diag::err_uninitialized_member_in_ctor)
+      << (int)Constructor->isImplicit() 
+      << SemaRef.Context.getTagDeclType(Constructor->getParent())
+      << 1 << Field->getDeclName();
+      SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
+      return true;
+    }
   }
   
   // Nothing to initialize.
diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp
new file mode 100644 (file)
index 0000000..86c5fd1
--- /dev/null
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+void fn() = default; // expected-error {{only special member}}
+struct foo {
+  void fn() = default; // expected-error {{only special member}}
+
+  foo() = default;
+  foo(const foo&) = default;
+  foo(foo&) = default;
+  foo& operator = (const foo&) = default;
+  foo& operator = (foo&) = default;
+  ~foo() = default;
+};
+
+struct bar {
+  bar();
+  bar(const bar&);
+  bar(bar&);
+  bar& operator = (const bar&);
+  bar& operator = (bar&);
+  ~bar();
+};
+
+bar::bar() = default;
+bar::bar(const bar&) = default;
+bar::bar(bar&) = default;
+bar& bar::operator = (const bar&) = default;
+bar& bar::operator = (bar&) = default;
+bar::~bar() = default;
+
+// FIXME: static_assert(__is_trivial(foo), "foo should be trivial");
+
+static_assert(!__has_trivial_destructor(bar), "bar's destructor isn't trivial");
+static_assert(!__has_trivial_constructor(bar),
+              "bar's default constructor isn't trivial");
+static_assert(!__has_trivial_copy(bar), "bar has no trivial copy");
+static_assert(!__has_trivial_assign(bar), "bar has no trivial assign");
+
+void tester() {
+  foo f, g(f);
+  bar b, c(b);
+  f = g;
+  b = c;
+}
+
diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
new file mode 100644 (file)
index 0000000..0bf8914
--- /dev/null
@@ -0,0 +1,49 @@
+// 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 bad_union { // expected-note {{marked deleted here}}
+  non_trivial nt;
+};
+bad_union u; // expected-error {{call to deleted constructor}}
+union bad_union2 { // expected-note {{marked deleted here}}
+  const int i;
+};
+bad_union2 u2; // expected-error {{call to deleted constructor}}
+
+struct bad_anon { // expected-note {{marked deleted here}}
+  union {
+    non_trivial nt;
+  };
+};
+bad_anon a; // expected-error {{call to deleted constructor}}
+struct bad_anon2 { // expected-note {{marked deleted here}}
+  union {
+    const int i;
+  };
+};
+bad_anon2 a2; // expected-error {{call to deleted constructor}}
+
+// This would be great except that we implement
+union good_union {
+  const int i;
+  float f;
+};
+good_union gu;
+struct good_anon {
+  union {
+    const int i;
+    float f;
+  };
+};
+good_anon ga;
+
+struct good : non_trivial {
+  non_trivial nt;
+};
+good g;
index 9da85567beda64f9ead56d1ea8ad858299493b06..e783f4982605942c3adc44d7dc0599eb52b7d644 100644 (file)
@@ -59,3 +59,10 @@ namespace PR7948 {
   struct S { const int x; ~S(); };
   const S arr[2] = { { 42 } };
 }
+
+// This is valid
+union U {
+  const int i;
+  float f;
+};
+U u;