diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-10 23:43:53 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-10 23:43:53 +0000 |
commit | 275a369f003f25bd22c00c1c0fc0251c7208caf4 (patch) | |
tree | f9088a9b40a3ce195904954931a36c1adb532f15 /lib/Sema/Sema.cpp | |
parent | dd98e2cad165ca73c769e4f105a4e47c2216387a (diff) |
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
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r-- | lib/Sema/Sema.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 57ed9884ba..d8610133f2 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -218,7 +218,52 @@ void Sema::DeleteStmt(StmtTy *S) { /// 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(); + } + } + } + } } |