diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-12-07 00:22:08 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-12-07 00:22:08 +0000 |
commit | 721e77db41cd9a07d2e1c9fdf08a4bd2eee1bc98 (patch) | |
tree | d334eab83c69f0725406b75d6dfd61dab106e1af | |
parent | 19a9edb5dd7ab2c63249b28f45f16781a5577874 (diff) |
Move RequireCompleteType requirement for fields early into ActOnField so that
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
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 6 | ||||
-rw-r--r-- | test/CodeGenCXX/default-constructor-template-member.cpp | 10 | ||||
-rw-r--r-- | test/Sema/nested-redef.c | 3 | ||||
-rw-r--r-- | test/SemaObjC/ivar-sem-check-1.m | 3 |
5 files changed, 31 insertions, 12 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0fa5780e98..01314c31cf 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 6a4ac3c562..b1a58038a9 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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 index 0000000000..e0a17e0e4f --- /dev/null +++ b/test/CodeGenCXX/default-constructor-template-member.cpp @@ -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 diff --git a/test/Sema/nested-redef.c b/test/Sema/nested-redef.c index ea18091012..54a970f044 100644 --- a/test/Sema/nested-redef.c +++ b/test/Sema/nested-redef.c @@ -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 { }; diff --git a/test/SemaObjC/ivar-sem-check-1.m b/test/SemaObjC/ivar-sem-check-1.m index 957abc397e..4e53015b2e 100644 --- a/test/SemaObjC/ivar-sem-check-1.m +++ b/test/SemaObjC/ivar-sem-check-1.m @@ -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}} |