aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-12-07 00:22:08 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-12-07 00:22:08 +0000
commit721e77db41cd9a07d2e1c9fdf08a4bd2eee1bc98 (patch)
treed334eab83c69f0725406b75d6dfd61dab106e1af
parent19a9edb5dd7ab2c63249b28f45f16781a5577874 (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.cpp21
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp6
-rw-r--r--test/CodeGenCXX/default-constructor-template-member.cpp10
-rw-r--r--test/Sema/nested-redef.c3
-rw-r--r--test/SemaObjC/ivar-sem-check-1.m3
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}}