Add type checking for tentative definitions at the end of the
translation unit.
Thread the various declarations of variables via
VarDecl::getPreviousDeclaration.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66601 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 57ed988..d861013 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -218,7 +218,52 @@
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
+ // 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. If a translation unit
+ // contains one or more tentative definitions for an identifier,
+ // and the translation unit contains no external definition for
+ // that identifier, then the behavior is exactly as if the
+ // translation unit contains a file scope declaration of that
+ // identifier, with the composite type as of the end of the
+ // translation unit, with an initializer equal to 0.
+ if (!getLangOptions().CPlusPlus) {
+ // Note: we traverse the scope's list of declarations rather than
+ // the DeclContext's list, because we only want to see the most
+ // recent declaration of each identifier.
+ for (Scope::decl_iterator I = TUScope->decl_begin(),
+ IEnd = TUScope->decl_end();
+ I != IEnd; ++I) {
+ Decl *D = static_cast<Decl *>(*I);
+ if (D->isInvalidDecl())
+ continue;
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->isTentativeDefinition(Context)) {
+ if (const IncompleteArrayType *ArrayT
+ = Context.getAsIncompleteArrayType(VD->getType())) {
+ if (RequireCompleteType(VD->getLocation(),
+ ArrayT->getElementType(),
+ diag::err_tentative_def_incomplete_type_arr))
+ VD->setInvalidDecl();
+ else {
+ // Set the length of the array to 1 (C99 6.9.2p5).
+ llvm::APSInt One(Context.getTypeSize(Context.getSizeType()),
+ true);
+ QualType T
+ = Context.getConstantArrayType(ArrayT->getElementType(),
+ One, ArrayType::Normal, 0);
+ VD->setType(T);
+ }
+ } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
+ diag::err_tentative_def_incomplete_type))
+ VD->setInvalidDecl();
+ }
+ }
+ }
+ }
}