From a03aca82de5259846d4ef38db11b8116398d2222 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 10 Mar 2009 21:58:27 +0000 Subject: [PATCH] Partial fix for PR3310, concerning type-checking for tentative definitions. We were rejecting tentative definitions of incomplete (which is bad), and now we don't. This fix is partial because we don't do the end-of-translation-unit initialization for tentative definitions that don't ever have any initializers specified. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66584 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 34 ++++++++++++++++++++++++---------- test/Sema/bitfield.c | 2 +- test/Sema/enum.c | 6 ++---- test/Sema/incomplete-decl.c | 4 ++-- test/Sema/tentative-decls.c | 8 ++++++++ 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 049c939452..c5768fd73a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1749,6 +1749,13 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } + if (!InvalidDecl && R->isVoidType() && !NewVD->hasExternalStorage()) { + Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) + << R; + InvalidDecl = true; + } + + // If this is a locally-scoped extern C variable, update the map of // such variables. if (CurContext->isFunctionOrMethod() && NewVD->isExternC(Context) && @@ -2342,17 +2349,25 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) { // storage-class specifier or with the storage-class specifier "static", // constitutes a tentative definition. Note: A tentative definition with // external linkage is valid (C99 6.2.2p5). - if (isTentativeDefinition(IDecl)) { - if (T->isIncompleteArrayType()) { - // C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete - // array to be completed. Don't issue a diagnostic. - } else if (!IDecl->isInvalidDecl() && - RequireCompleteType(IDecl->getLocation(), T, - diag::err_typecheck_decl_incomplete_type)) + if (!getLangOptions().CPlusPlus && isTentativeDefinition(IDecl)) { + QualType CheckType = T; + unsigned DiagID = diag::err_typecheck_decl_incomplete_type; + + const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(T); + if (ArrayT) { + CheckType = ArrayT->getElementType(); + DiagID = diag::err_illegal_decl_array_incomplete_type; + } + + if (IDecl->isInvalidDecl()) { + // Do nothing with invalid declarations + } else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) && + RequireCompleteType(IDecl->getLocation(), CheckType, DiagID)) { // C99 6.9.2p3: If the declaration of an identifier for an object is // a tentative definition and has internal linkage (C99 6.2.2p3), the // declared type shall not be an incomplete type. IDecl->setInvalidDecl(); + } } if (IDecl->isFileVarDecl()) CheckForFileScopedRedefinitions(S, IDecl); @@ -3243,9 +3258,8 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isIntegralType()) { // Handle incomplete types with specific error. - if (FieldTy->isIncompleteType()) - return Diag(FieldLoc, diag::err_field_incomplete) - << FieldTy << BitWidth->getSourceRange(); + if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) + return true; return Diag(FieldLoc, diag::err_not_integral_type_bitfield) << FieldName << BitWidth->getSourceRange(); } diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c index 2e4df47650..7a70fe8de8 100644 --- a/test/Sema/bitfield.c +++ b/test/Sema/bitfield.c @@ -1,5 +1,5 @@ // RUN: clang %s -fsyntax-only -verify -enum e0; +enum e0; // expected-note{{forward declaration of 'enum e0'}} struct a { int a : -1; // expected-error{{bit-field 'a' has negative width}} diff --git a/test/Sema/enum.c b/test/Sema/enum.c index ce49f3064d..37c9a1e7cf 100644 --- a/test/Sema/enum.c +++ b/test/Sema/enum.c @@ -21,13 +21,11 @@ int test() { return sizeof(enum e) ; } -enum gccForwardEnumExtension ve; // expected-error {{variable has incomplete type 'enum gccForwardEnumExtension'}} \ - // expected-warning{{ISO C forbids forward references to 'enum' types}} \ - // expected-note{{forward declaration of 'enum gccForwardEnumExtension'}} +enum gccForwardEnumExtension ve; // expected-warning{{ISO C forbids forward references to 'enum' types}} int test2(int i) { - ve + i; + ve + i; // expected-error{{invalid operands to binary expression}} } // PR2020 diff --git a/test/Sema/incomplete-decl.c b/test/Sema/incomplete-decl.c index be52cfd707..7ec436acce 100644 --- a/test/Sema/incomplete-decl.c +++ b/test/Sema/incomplete-decl.c @@ -1,9 +1,9 @@ // RUN: clang -fsyntax-only -verify %s -struct foo; // expected-note 4 {{forward declaration of 'struct foo'}} +struct foo; // expected-note 3 {{forward declaration of 'struct foo'}} void b; // expected-error {{variable has incomplete type 'void'}} -struct foo f; // expected-error {{variable has incomplete type 'struct foo'}} +struct foo f; // // FIXME: error because 'struct foo' is never defined static void c; // expected-error {{variable has incomplete type 'void'}} static struct foo g; // expected-error {{variable has incomplete type 'struct foo'}} diff --git a/test/Sema/tentative-decls.c b/test/Sema/tentative-decls.c index 12ce181e0f..3c1ab0e658 100644 --- a/test/Sema/tentative-decls.c +++ b/test/Sema/tentative-decls.c @@ -1,5 +1,12 @@ // RUN: clang %s -fsyntax-only -verify +// PR3310 +struct a x1; // expected-note 2{{forward declaration of 'struct a'}} +static struct a x2; // expected-error{{variable has incomplete type 'struct a'}} +struct a x3[10]; // expected-error{{array has incomplete element type 'struct a'}} +struct a {int x;}; +struct b x4; // FIXME: error because 'struct b' is never defined + const int a [1] = {1}; extern const int a[]; @@ -43,3 +50,4 @@ void func2(void) extern double *p; extern double *p; } + -- 2.40.0