diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.cpp | 65 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 17 |
3 files changed, 57 insertions, 33 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index ed5c431da82..19155b6cc34 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" @@ -232,41 +233,39 @@ void Sema::ActOnEndOfTranslationUnit() { // 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 = (*I).getAs<Decl>(); - if (D->isInvalidDecl()) - continue; + for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator + D = TentativeDefinitions.begin(), + DEnd = TentativeDefinitions.end(); + D != DEnd; ++D) { + VarDecl *VD = D->second; - 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). - Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); - llvm::APInt 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(); - } + if (VD->isInvalidDecl() || !VD->isTentativeDefinition(Context)) + continue; + + 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). + Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); + llvm::APInt 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(); + + // Notify the consumer that we've completed a tentative definition. + if (!VD->isInvalidDecl()) + Consumer.CompleteTentativeDefinition(VD); + } } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 1f6cd0440c4..f3c337c148e 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -233,6 +233,14 @@ public: /// not visible. llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls; + /// \brief The set of tentative declarations seen so far in this + /// translation unit for which no definition has been seen. + /// + /// The tentative declarations are indexed by the name of the + /// declaration, and only the most recent tentative declaration for + /// a given variable will be recorded here. + llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions; + IdentifierResolver IdResolver; // Enum values used by KnownFunctionIDs (see below). diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 716219c034a..abde26ae533 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2545,6 +2545,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // Attach the initializer to the decl. VDecl->setInit(Init); + + // If the previous declaration of VDecl was a tentative definition, + // remove it from the set of tentative definitions. + if (VDecl->getPreviousDeclaration() && + VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) { + llvm::DenseMap<DeclarationName, VarDecl *>::iterator Pos + = TentativeDefinitions.find(VDecl->getDeclName()); + assert(Pos != TentativeDefinitions.end() && + "Unrecorded tentative definition?"); + TentativeDefinitions.erase(Pos); + } + return; } @@ -2557,6 +2569,11 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) { QualType Type = Var->getType(); + + // Record tentative definitions. + if (Var->isTentativeDefinition(Context)) + TentativeDefinitions[Var->getDeclName()] = Var; + // C++ [dcl.init.ref]p3: // The initializer can be omitted for a reference only in a // parameter declaration (8.3.5), in the declaration of a |

