From: Nick Lewycky Date: Thu, 31 Jan 2013 03:23:57 +0000 (+0000) Subject: Remove elements from Sema.UndefinedInternals as functions are defined. Also X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=995e26b0523ac8e3b6199a509b871b81fa5df6ee;p=clang Remove elements from Sema.UndefinedInternals as functions are defined. Also filter the elements before emitting them into a PCH. No user-visible functionality change, except that PCH files may be smaller? git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174034 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 24a4fc2a57..6693dc8683 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -68,7 +68,7 @@ public: SmallVectorImpl &Namespaces); virtual void ReadUndefinedInternals( - llvm::MapVector &Undefined); + llvm::DenseMap &Undefined); /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index cb57f23cc9..494ba656bb 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -254,7 +254,7 @@ public: virtual void ReadKnownNamespaces(SmallVectorImpl &Namespaces); virtual void ReadUndefinedInternals( - llvm::MapVector &Undefined); + llvm::DenseMap &Undefined); /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 58e663d917..b77897a243 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -736,11 +736,15 @@ public: // Contains the locations of the beginning of unparsed default // argument locations. - llvm::DenseMap UnparsedDefaultArgLocs; + llvm::DenseMap UnparsedDefaultArgLocs; /// UndefinedInternals - all the used, undefined objects with /// internal linkage in this translation unit. - llvm::MapVector UndefinedInternals; + llvm::DenseMap UndefinedInternals; + + /// Obtain a sorted list of functions that are undefined but ODR-used. + void getUndefinedInternals( + llvm::SmallVectorImpl > &Undefined); typedef std::pair GlobalMethods; typedef llvm::DenseMap GlobalMethodPool; diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 2dd698ed5c..aa3633b4b3 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1521,7 +1521,7 @@ public: SmallVectorImpl &Namespaces); virtual void ReadUndefinedInternals( - llvm::MapVector &Undefined); + llvm::DenseMap &Undefined); virtual void ReadTentativeDefinitions( SmallVectorImpl &TentativeDefs); diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp index 8df830aeff..609324d32d 100644 --- a/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/lib/Sema/MultiplexExternalSemaSource.cpp @@ -202,7 +202,7 @@ void MultiplexExternalSemaSource::ReadKnownNamespaces( } void MultiplexExternalSemaSource::ReadUndefinedInternals( - llvm::MapVector &Undefined){ + llvm::DenseMap &Undefined){ for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadUndefinedInternals(Undefined); } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 5764355144..76ea996ec5 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -366,46 +366,70 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { } namespace { - struct UndefinedInternal { - NamedDecl *decl; - FullSourceLoc useLoc; - - UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc) - : decl(decl), useLoc(useLoc) {} + struct SortUndefinedInternal { + const SourceManager &SM; + explicit SortUndefinedInternal(SourceManager &SM) : SM(SM) {} + + bool operator()(const std::pair &l, + const std::pair &r) const { + if (l.second != r.second) + return SM.isBeforeInTranslationUnit(l.second, r.second); + return SM.isBeforeInTranslationUnit(l.first->getLocation(), + r.first->getLocation()); + } }; } -/// checkUndefinedInternals - Check for undefined objects with internal linkage. -static void checkUndefinedInternals(Sema &S) { - if (S.UndefinedInternals.empty()) return; - - // Collect all the still-undefined entities with internal linkage. - SmallVector undefined; - for (llvm::MapVector::iterator - i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end(); - i != e; ++i) { - NamedDecl *decl = i->first; +/// Obtains a sorted list of functions that are undefined but ODR-used. +void Sema::getUndefinedInternals( + SmallVectorImpl > &Undefined) { + for (llvm::DenseMap::iterator + I = UndefinedInternals.begin(), E = UndefinedInternals.end(); + I != E; ++I) { + NamedDecl *ND = I->first; // Ignore attributes that have become invalid. - if (decl->isInvalidDecl()) continue; + if (ND->isInvalidDecl()) continue; // If we found out that the decl is external, don't warn. - if (decl->getLinkage() == ExternalLinkage) continue; + if (ND->getLinkage() == ExternalLinkage) continue; // __attribute__((weakref)) is basically a definition. - if (decl->hasAttr()) continue; + if (ND->hasAttr()) continue; - if (FunctionDecl *fn = dyn_cast(decl)) { - if (fn->isDefined()) + if (FunctionDecl *FD = dyn_cast(ND)) { + if (FD->isDefined()) continue; } else { - if (cast(decl)->hasDefinition() != VarDecl::DeclarationOnly) + if (cast(ND)->hasDefinition() != VarDecl::DeclarationOnly) continue; } - S.Diag(decl->getLocation(), diag::warn_undefined_internal) - << isa(decl) << decl; - S.Diag(i->second, diag::note_used_here); + Undefined.push_back(std::make_pair(ND, I->second)); + } + + // Sort (in order of use site) so that we're not (as) dependent on + // the iteration order through an llvm::DenseMap. + std::sort(Undefined.begin(), Undefined.end(), + SortUndefinedInternal(Context.getSourceManager())); +} + +/// checkUndefinedInternals - Check for undefined objects with internal linkage. +static void checkUndefinedInternals(Sema &S) { + if (S.UndefinedInternals.empty()) return; + + // Collect all the still-undefined entities with internal linkage. + SmallVector, 16> Undefined; + S.getUndefinedInternals(Undefined); + if (Undefined.empty()) return; + + for (SmallVectorImpl >::iterator + I = Undefined.begin(), E = Undefined.end(); I != E; ++I) { + NamedDecl *ND = I->first; + + S.Diag(ND->getLocation(), diag::warn_undefined_internal) + << isa(ND) << ND; + S.Diag(I->second, diag::note_used_here); } } @@ -1065,7 +1089,7 @@ void ExternalSemaSource::ReadKnownNamespaces( } void ExternalSemaSource::ReadUndefinedInternals( - llvm::MapVector &Undefined) { + llvm::DenseMap &Undefined) { } void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 80543fd532..834041c65c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8428,6 +8428,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); + // The only way to be included in UndefinedInternals is if there is an + // ODR-use before the definition. Avoid the expensive map lookup if this + // is the first declaration. + if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed() && + FD->getLinkage() != ExternalLinkage) + UndefinedInternals.erase(FD); + // If the function implicitly returns zero (like 'main') or is naked, // don't complain about missing return statements. if (FD->hasImplicitReturnZero() || FD->hasAttr()) diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index ac86d41eb1..d38b5308de 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1,4 +1,4 @@ -//===--- ASTReader.cpp - AST File Reader ------------------------*- C++ -*-===// +//===--- ASTReader.cpp - AST File Reader ----------------------------------===// // // The LLVM Compiler Infrastructure // @@ -5963,7 +5963,7 @@ void ASTReader::ReadKnownNamespaces( } void ASTReader::ReadUndefinedInternals( - llvm::MapVector &Undefined) { + llvm::DenseMap &Undefined) { for (unsigned Idx = 0, N = UndefinedInternals.size(); Idx != N;) { NamedDecl *D = cast(GetDecl(UndefinedInternals[Idx++])); SourceLocation Loc = diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 25e3d52f37..8120799c11 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3590,10 +3590,11 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Build a record of all used, undefined objects with internal linkage. RecordData UndefinedInternals; - for (llvm::MapVector::iterator - I = SemaRef.UndefinedInternals.begin(), - IEnd = SemaRef.UndefinedInternals.end(); - I != IEnd; ++I) { + + SmallVector, 16> Undefined; + SemaRef.getUndefinedInternals(Undefined); + for (SmallVectorImpl >::iterator + I = Undefined.begin(), E = Undefined.end(); I != E; ++I) { AddDeclRef(I->first, UndefinedInternals); AddSourceLocation(I->second, UndefinedInternals); }