]> granicus.if.org Git - clang/commitdiff
Move RequireCompleteType requirement for fields early into ActOnField so that
authorEli Friedman <eli.friedman@gmail.com>
Mon, 7 Dec 2009 00:22:08 +0000 (00:22 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 7 Dec 2009 00:22:08 +0000 (00:22 +0000)
subsequent code which depends on a complete type does the right thing.

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

lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/CodeGenCXX/default-constructor-template-member.cpp [new file with mode: 0644]
test/Sema/nested-redef.c
test/SemaObjC/ivar-sem-check-1.m

index 0fa5780e9829993b0484487cd02664883e1e7c98..01314c31cf4fdc9ed061ce78f857ae0732c438ae 100644 (file)
@@ -5044,9 +5044,14 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
     T = Context.IntTy;
   }
 
+  QualType EltTy = Context.getBaseElementType(T);
+  if (!EltTy->isDependentType() &&
+      RequireCompleteType(Loc, EltTy, diag::err_field_incomplete))
+    InvalidDecl = true;
+
   // C99 6.7.2.1p8: A member of a structure or union may have any type other
   // than a variably modified type.
-  if (T->isVariablyModifiedType()) {
+  if (!InvalidDecl && T->isVariablyModifiedType()) {
     bool SizeIsNegative;
     QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
                                                            SizeIsNegative);
@@ -5063,13 +5068,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
   }
 
   // Fields can not have abstract class types
-  if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl,
-                             AbstractFieldType))
+  if (!InvalidDecl && RequireNonAbstractType(Loc, T,
+                                             diag::err_abstract_type_in_decl,
+                                             AbstractFieldType))
     InvalidDecl = true;
 
   bool ZeroWidth = false;
   // If this is declared as a bit-field, check the bit-field.
-  if (BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
+  if (!InvalidDecl && BitWidth &&
+      VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
     InvalidDecl = true;
     DeleteExpr(BitWidth);
     BitWidth = 0;
@@ -5088,8 +5095,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
   }
 
   if (getLangOptions().CPlusPlus) {
-    QualType EltTy = Context.getBaseElementType(T);
-
     CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
 
     if (!T->isPODType())
@@ -5432,8 +5437,10 @@ void Sema::ActOnFields(Scope* S,
 
     // If the field is already invalid for some reason, don't emit more
     // diagnostics about it.
-    if (FD->isInvalidDecl())
+    if (FD->isInvalidDecl()) {
+      EnclosingDecl->setInvalidDecl();
       continue;
+    }
 
     // C99 6.7.2.1p2:
     //   A structure or union shall not contain a member with
index 6a4ac3c5628a7bb20baafe3a9d58f3efafe5be88..b1a58038a976f0cafe5113b8621cc2c314c6b7ec 100644 (file)
@@ -1060,10 +1060,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
        Member != MemberEnd; ++Member) {
     Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
     if (NewMember) {
-      if (NewMember->isInvalidDecl()) {
-        Invalid = true;
-      } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
         Fields.push_back(DeclPtrTy::make(Field));
+      else if (NewMember->isInvalidDecl())
+        Invalid = true;
     } else {
       // FIXME: Eventually, a NULL return will mean that one of the
       // instantiations was a semantic disaster, and we'll want to set Invalid =
diff --git a/test/CodeGenCXX/default-constructor-template-member.cpp b/test/CodeGenCXX/default-constructor-template-member.cpp
new file mode 100644 (file)
index 0000000..e0a17e0
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: clang-cc -emit-llvm %s -o - | FileCheck %s
+
+template <class T> struct A { A(); };
+struct B { A<int> x; };
+void a() {   
+  B b;
+}
+// CHECK: call void @_ZN1BC1Ev
+// CHECK: define linkonce_odr void @_ZN1BC1Ev
+// CHECK: call void @_ZN1AIiEC1Ev
index ea180910128b95ca100ad721a106c1155208505f..54a970f044212df6fd4f361be27db03e09561e07 100644 (file)
@@ -1,6 +1,7 @@
 // RUN: clang-cc -fsyntax-only -verify %s
 struct X { // expected-note{{previous definition is here}}
-  struct X { } x; // expected-error{{nested redefinition of 'X'}}
+  struct X { } x; // expected-error{{nested redefinition of 'X'}} \
+                  // expected-error{{field has incomplete type}}
 }; 
 
 struct Y { };
index 957abc397e89846f65a273ad230f9e512d4e1708..4e53015b2e92b89fbe4015150856540d1d8d7b29 100644 (file)
@@ -9,7 +9,8 @@ typedef int FOO();
        int arr[];  // expected-error {{field has incomplete type}}
        struct S IC;  // expected-error {{field has incomplete type}}
        struct T { // expected-note {{previous definition is here}}
-         struct T {} X;  // expected-error {{nested redefinition of 'T'}}
+         struct T {} X;  // expected-error {{nested redefinition of 'T'}} \
+                         // expected-error {{field has incomplete type}}
        }YYY; 
        FOO    BADFUNC;  // expected-error {{field 'BADFUNC' declared as a function}}
        int kaka;       // expected-note {{previous declaration is here}}