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 | ec8b59ffc30c65051070e6d6cbb8e4b419210d18 (patch) | |
tree | a2521d2b58760bd1b6fcdc1ae59aa9dc9a5510a8 /lib/Sema/SemaDecl.cpp | |
parent | 520035439d7133064325c4df6378c5a8f2f05539 (diff) |
Improve GCC compatibility by allowing static tentative definitions of
incomplete type (with a warning), from Enea Zaffanella!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76451 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 28ac9d1982..d1d06e3284 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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); } } } |