diff options
author | Chris Lattner <sabre@nondot.org> | 2009-09-08 18:19:27 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-09-08 18:19:27 +0000 |
commit | 63d65f873fdfcb04b216ea9c648d1df5992aed1c (patch) | |
tree | 04893bf1ec4c6a143233a4efb96630d1d1d283a3 /lib | |
parent | c4f1fb125d4fe2c8879030d6f6e8b2f75cb681f1 (diff) |
Fix PR4922, where Sema would complete tentative definitions in nondeterminstic
order because it was doing so while iterating over a densemap.
There are still similar problems in other places, for example
WeakUndeclaredIdentifiers is still written to the PCH file in a nondeterminstic
order, and we emit warnings about #pragma weak in nondeterminstic order.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81236 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 23 |
5 files changed, 53 insertions, 37 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index a7e6c0c8f9..f4d06c068b 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2225,6 +2225,7 @@ void PCHReader::InitializeSema(Sema &S) { for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I])); SemaObj->TentativeDefinitions[Var->getDeclName()] = Var; + SemaObj->TentativeDefinitionList.push_back(Var->getDeclName()); } // If there were any locally-scoped external declarations, diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 985d99abbe..86a52fcf52 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1800,19 +1800,22 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, getIdentifierRef(&Table.get(BuiltinNames[I])); } - // Build a record containing all of the tentative definitions in - // this header file. Generally, this record will be empty. + // Build a record containing all of the tentative definitions in this file, in + // TentativeDefinitionList order. Generally, this record will be empty for + // headers. RecordData TentativeDefinitions; - for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator - TD = SemaRef.TentativeDefinitions.begin(), - TDEnd = SemaRef.TentativeDefinitions.end(); - TD != TDEnd; ++TD) - AddDeclRef(TD->second, TentativeDefinitions); + for (unsigned i = 0, e = SemaRef.TentativeDefinitionList.size(); i != e; ++i){ + VarDecl *VD = + SemaRef.TentativeDefinitions.lookup(SemaRef.TentativeDefinitionList[i]); + if (VD) AddDeclRef(VD, TentativeDefinitions); + } // Build a record containing all of the locally-scoped external // declarations in this header file. Generally, this record will be // empty. RecordData LocallyScopedExternalDecls; + // FIXME: This is filling in the PCH file in densemap order which is + // nondeterminstic! for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator TD = SemaRef.LocallyScopedExternalDecls.begin(), TDEnd = SemaRef.LocallyScopedExternalDecls.end(); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index b41902c15f..2d72c3e1be 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -256,13 +256,16 @@ void Sema::ActOnEndOfTranslationUnit() { // template instantiations earlier. PerformPendingImplicitInstantiations(); - // check for #pragma weak identifiers that were never declared + // Check for #pragma weak identifiers that were never declared + // FIXME: This will cause diagnostics to be emitted in a non-determinstic + // order! Iterating over a densemap like this is bad. for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator - I = WeakUndeclaredIdentifiers.begin(), - E = WeakUndeclaredIdentifiers.end(); I != E; ++I) { - if (!I->second.getUsed()) - Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared) - << I->first; + I = WeakUndeclaredIdentifiers.begin(), + E = WeakUndeclaredIdentifiers.end(); I != E; ++I) { + if (I->second.getUsed()) continue; + + Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared) + << I->first; } if (!CompleteTranslationUnit) @@ -279,31 +282,30 @@ 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. - for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator - D = TentativeDefinitions.begin(), - DEnd = TentativeDefinitions.end(); - D != DEnd; ++D) { - VarDecl *VD = D->second; - - if (VD->isInvalidDecl() || !VD->isTentativeDefinition(Context)) + for (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) { + VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]); + + // If the tentative definition was completed, it will be in the list, but + // not the map. + if (VD == 0 || 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)) + 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.getConstantArrayWithoutExprType(ArrayT->getElementType(), - One, ArrayType::Normal, 0); - VD->setType(T); + continue; } + + // 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.getConstantArrayWithoutExprType(ArrayT->getElementType(), + One, ArrayType::Normal, 0); + VD->setType(T); } else if (RequireCompleteType(VD->getLocation(), VD->getType(), diag::err_tentative_def_incomplete_type)) VD->setInvalidDecl(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7c4bcab2de..ee893e2e0d 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -266,6 +266,7 @@ public: /// declaration, and only the most recent tentative declaration for /// a given variable will be recorded here. llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions; + std::vector<DeclarationName> TentativeDefinitionList; /// WeakUndeclaredIdentifiers - Identifiers contained in /// #pragma weak before declared. rare. may alias another diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d37f4485ff..6f04f7b162 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3208,11 +3208,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // 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); + bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName()); + assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted; } return; @@ -3230,8 +3227,20 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, QualType Type = Var->getType(); // Record tentative definitions. - if (Var->isTentativeDefinition(Context)) - TentativeDefinitions[Var->getDeclName()] = Var; + if (Var->isTentativeDefinition(Context)) { + std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool> + InsertPair = + TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var)); + + // Keep the latest definition in the map. If we see 'int i; int i;' we + // want the second one in the map. + InsertPair.first->second = Var; + + // However, for the list, we don't care about the order, just make sure + // that there are no dupes for a given declaration name. + if (InsertPair.second) + TentativeDefinitionList.push_back(Var->getDeclName()); + } // C++ [dcl.init.ref]p3: // The initializer can be omitted for a reference only in a |