diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-07-20 18:46:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-07-20 18:46:59 +0000 |
commit | 47d2859b3e27c3ce904ac62249d4297e6bf9726d (patch) | |
tree | 2a0e74ab0628e2c67e5c499f11964597170f44a6 | |
parent | af9f362840f8d69cc15102dec1e735b70d1aee73 (diff) | |
download | bcm5719-llvm-47d2859b3e27c3ce904ac62249d4297e6bf9726d.tar.gz bcm5719-llvm-47d2859b3e27c3ce904ac62249d4297e6bf9726d.zip |
Improve GCC compatibility by allowing static tentative definitions of
incomplete type (with a warning), from Enea Zaffanella!
llvm-svn: 76451
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 35 | ||||
-rw-r--r-- | clang/test/Sema/incomplete-decl.c | 5 | ||||
-rw-r--r-- | clang/test/Sema/tentative-decls.c | 2 |
4 files changed, 25 insertions, 19 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7fc237bf0b1..2864ed2ad67 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1206,6 +1206,8 @@ def err_typecheck_pointer_arith_void_type : Error< "arithmetic on pointer to void type">; def err_typecheck_decl_incomplete_type : Error< "variable has incomplete type %0">; +def ext_typecheck_decl_incomplete_type : ExtWarn< + "tentative definition of variable with internal linkage has incomplete non-array type %0">; def err_tentative_def_incomplete_type : Error< "tentative definition has type %0 that is never completed">; def err_tentative_def_incomplete_type_arr : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 28ac9d1982a..d1d06e32848 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2899,29 +2899,32 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, diag::err_typecheck_decl_incomplete_type)) IDecl->setInvalidDecl(); } - // File scope. C99 6.9.2p2: A declaration of an identifier for and + // File scope. C99 6.9.2p2: A declaration of an identifier for an // object that has file scope without an initializer, and without a // 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 (IDecl->isTentativeDefinition(Context)) { - 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->isTentativeDefinition(Context) && !IDecl->isInvalidDecl()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(T)) { + if (RequireCompleteType(IDecl->getLocation(), + ArrayT->getElementType(), + diag::err_illegal_decl_array_incomplete_type)) + IDecl->setInvalidDecl(); } - - if (IDecl->isInvalidDecl()) { - // Do nothing with invalid declarations - } else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) && - RequireCompleteType(IDecl->getLocation(), CheckType, DiagID)) { + else if (IDecl->getStorageClass() == VarDecl::Static) { // 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 + // a tentative definition and has internal linkage (C99 6.2.2p3), the // declared type shall not be an incomplete type. - IDecl->setInvalidDecl(); + // NOTE: code such as the following + // static struct s; + // struct s { int a; }; + // is accepted by gcc. Hence here we issue a warning instead of + // an error and we do not invalidate the static declaration. + // NOTE: to avoid multiple warnings, only check the first declaration. + if (IDecl->getPreviousDeclaration() == 0) + RequireCompleteType(IDecl->getLocation(), T, + diag::ext_typecheck_decl_incomplete_type); } } } diff --git a/clang/test/Sema/incomplete-decl.c b/clang/test/Sema/incomplete-decl.c index eb93e8e3803..6a6ba753f3f 100644 --- a/clang/test/Sema/incomplete-decl.c +++ b/clang/test/Sema/incomplete-decl.c @@ -1,12 +1,13 @@ // RUN: clang-cc -fsyntax-only -verify %s -struct foo; // expected-note 4 {{forward declaration of 'struct foo'}} +struct foo; // expected-note 5 {{forward declaration of 'struct foo'}} void b; // expected-error {{variable has incomplete type 'void'}} struct foo f; // expected-error{{tentative definition has type 'struct foo' that is never completed}} static void c; // expected-error {{variable has incomplete type 'void'}} -static struct foo g; // expected-error {{variable has incomplete type 'struct foo'}} +static struct foo g; // expected-warning {{tentative definition of variable with internal linkage has incomplete non-array type 'struct foo'}} \ + expected-error{{tentative definition has type 'struct foo' that is never completed}} extern void d; extern struct foo e; diff --git a/clang/test/Sema/tentative-decls.c b/clang/test/Sema/tentative-decls.c index e3c893c7771..c94af1160b8 100644 --- a/clang/test/Sema/tentative-decls.c +++ b/clang/test/Sema/tentative-decls.c @@ -2,7 +2,7 @@ // PR3310 struct a x1; // expected-note 2{{forward declaration of 'struct a'}} -static struct a x2; // expected-error{{variable has incomplete type 'struct a'}} +static struct a x2; // expected-warning{{tentative definition of variable with internal linkage has incomplete non-array type 'struct a'}} struct a x3[10]; // expected-error{{array has incomplete element type 'struct a'}} struct a {int x;}; static struct a x2_okay; |