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?

llvm-svn: 174034
This commit is contained in:
Nick Lewycky 2013-01-31 03:23:57 +00:00
parent 60bd4be17a
commit f0f5616457
9 changed files with 78 additions and 42 deletions

View File

@ -68,7 +68,7 @@ public:
SmallVectorImpl<NamespaceDecl *> &Namespaces);
virtual void ReadUndefinedInternals(
llvm::MapVector<NamedDecl*, SourceLocation> &Undefined);
llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined);
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.

View File

@ -254,7 +254,7 @@ public:
virtual void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces);
virtual void ReadUndefinedInternals(
llvm::MapVector<NamedDecl*, SourceLocation> &Undefined);
llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined);
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.

View File

@ -736,11 +736,15 @@ public:
// Contains the locations of the beginning of unparsed default
// argument locations.
llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
llvm::DenseMap<ParmVarDecl *, SourceLocation> UnparsedDefaultArgLocs;
/// UndefinedInternals - all the used, undefined objects with
/// internal linkage in this translation unit.
llvm::MapVector<NamedDecl*, SourceLocation> UndefinedInternals;
llvm::DenseMap<NamedDecl *, SourceLocation> UndefinedInternals;
/// Obtain a sorted list of functions that are undefined but ODR-used.
void getUndefinedInternals(
llvm::SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;

View File

@ -1521,7 +1521,7 @@ public:
SmallVectorImpl<NamespaceDecl *> &Namespaces);
virtual void ReadUndefinedInternals(
llvm::MapVector<NamedDecl *, SourceLocation> &Undefined);
llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined);
virtual void ReadTentativeDefinitions(
SmallVectorImpl<VarDecl *> &TentativeDefs);

View File

@ -202,7 +202,7 @@ void MultiplexExternalSemaSource::ReadKnownNamespaces(
}
void MultiplexExternalSemaSource::ReadUndefinedInternals(
llvm::MapVector<NamedDecl*, SourceLocation> &Undefined){
llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadUndefinedInternals(Undefined);
}

View File

@ -366,46 +366,70 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
}
namespace {
struct UndefinedInternal {
NamedDecl *decl;
FullSourceLoc useLoc;
struct SortUndefinedInternal {
const SourceManager &SM;
explicit SortUndefinedInternal(SourceManager &SM) : SM(SM) {}
UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc)
: decl(decl), useLoc(useLoc) {}
bool operator()(const std::pair<NamedDecl *, SourceLocation> &l,
const std::pair<NamedDecl *, SourceLocation> &r) const {
if (l.second != r.second)
return SM.isBeforeInTranslationUnit(l.second, r.second);
return SM.isBeforeInTranslationUnit(l.first->getLocation(),
r.first->getLocation());
}
};
}
/// Obtains a sorted list of functions that are undefined but ODR-used.
void Sema::getUndefinedInternals(
SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
for (llvm::DenseMap<NamedDecl *, SourceLocation>::iterator
I = UndefinedInternals.begin(), E = UndefinedInternals.end();
I != E; ++I) {
NamedDecl *ND = I->first;
// Ignore attributes that have become invalid.
if (ND->isInvalidDecl()) continue;
// If we found out that the decl is external, don't warn.
if (ND->getLinkage() == ExternalLinkage) continue;
// __attribute__((weakref)) is basically a definition.
if (ND->hasAttr<WeakRefAttr>()) continue;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (FD->isDefined())
continue;
} else {
if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly)
continue;
}
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<UndefinedInternal, 16> undefined;
for (llvm::MapVector<NamedDecl*,SourceLocation>::iterator
i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
i != e; ++i) {
NamedDecl *decl = i->first;
SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
S.getUndefinedInternals(Undefined);
if (Undefined.empty()) return;
// Ignore attributes that have become invalid.
if (decl->isInvalidDecl()) continue;
for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
NamedDecl *ND = I->first;
// If we found out that the decl is external, don't warn.
if (decl->getLinkage() == ExternalLinkage) continue;
// __attribute__((weakref)) is basically a definition.
if (decl->hasAttr<WeakRefAttr>()) continue;
if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
if (fn->isDefined())
continue;
} else {
if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
continue;
}
S.Diag(decl->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(decl) << decl;
S.Diag(i->second, diag::note_used_here);
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
S.Diag(I->second, diag::note_used_here);
}
}
@ -1065,7 +1089,7 @@ void ExternalSemaSource::ReadKnownNamespaces(
}
void ExternalSemaSource::ReadUndefinedInternals(
llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {
llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) {
}
void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {

View File

@ -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<NakedAttr>())

View File

@ -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<NamedDecl*, SourceLocation> &Undefined) {
llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) {
for (unsigned Idx = 0, N = UndefinedInternals.size(); Idx != N;) {
NamedDecl *D = cast<NamedDecl>(GetDecl(UndefinedInternals[Idx++]));
SourceLocation Loc =

View File

@ -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<NamedDecl*, SourceLocation>::iterator
I = SemaRef.UndefinedInternals.begin(),
IEnd = SemaRef.UndefinedInternals.end();
I != IEnd; ++I) {
SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
SemaRef.getUndefinedInternals(Undefined);
for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
AddDeclRef(I->first, UndefinedInternals);
AddSourceLocation(I->second, UndefinedInternals);
}