aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp16
-rw-r--r--lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--lib/Sema/Sema.cpp61
-rw-r--r--lib/Sema/SemaExpr.cpp26
4 files changed, 95 insertions, 10 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d5e9dbf4fc..7d4b461f5a 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -637,14 +637,26 @@ void NamedDecl::ClearLinkageCache() {
if (const CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(this))
clearLinkageForClass(record);
- if (const ClassTemplateDecl *temp = dyn_cast<ClassTemplateDecl>(this)) {
+ if (ClassTemplateDecl *temp =
+ dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(this))) {
// Clear linkage for the template pattern.
CXXRecordDecl *record = temp->getTemplatedDecl();
record->HasCachedLinkage = 0;
clearLinkageForClass(record);
- // ...do we need to clear linkage for specializations, too?
+ // We need to clear linkage for specializations, too.
+ for (ClassTemplateDecl::spec_iterator
+ i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i)
+ i->ClearLinkageCache();
}
+
+ // Clear cached linkage for function template decls, too.
+ if (FunctionTemplateDecl *temp =
+ dyn_cast<FunctionTemplateDecl>(const_cast<NamedDecl*>(this)))
+ for (FunctionTemplateDecl::spec_iterator
+ i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i)
+ i->ClearLinkageCache();
+
}
Linkage NamedDecl::getLinkage() const {
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5a45df24fe..9e5d7cf112 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -983,7 +983,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
// Set linkage and visibility in case we never see a definition.
NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
if (LV.linkage() != ExternalLinkage) {
- GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+ // Don't set internal linkage on declarations.
} else {
if (D->hasAttr<DLLImportAttr>())
GV->setLinkage(llvm::GlobalValue::DLLImportLinkage);
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 7eb1c57412..23a3c24804 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -271,6 +271,65 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
return false;
}
+namespace {
+ struct UndefinedInternal {
+ NamedDecl *decl;
+ FullSourceLoc useLoc;
+
+ UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc)
+ : decl(decl), useLoc(useLoc) {}
+ };
+
+ bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) {
+ return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc);
+ }
+}
+
+/// 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.
+ llvm::SmallVector<UndefinedInternal, 16> undefined;
+ for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator
+ i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
+ i != e; ++i) {
+ NamedDecl *decl = i->first;
+
+ // Ignore attributes that have become invalid.
+ if (decl->isInvalidDecl()) continue;
+
+ // __attribute__((weakref)) is basically a definition.
+ if (decl->hasAttr<WeakRefAttr>()) continue;
+
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+ if (fn->isPure() || fn->hasBody())
+ continue;
+ } else {
+ if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
+ continue;
+ }
+
+ // We build a FullSourceLoc so that we can sort with array_pod_sort.
+ FullSourceLoc loc(i->second, S.Context.getSourceManager());
+ undefined.push_back(UndefinedInternal(decl, loc));
+ }
+
+ if (undefined.empty()) return;
+
+ // Sort (in order of use site) so that we're not (as) dependent on
+ // the iteration order through an llvm::DenseMap.
+ llvm::array_pod_sort(undefined.begin(), undefined.end());
+
+ for (llvm::SmallVectorImpl<UndefinedInternal>::iterator
+ i = undefined.begin(), e = undefined.end(); i != e; ++i) {
+ NamedDecl *decl = i->decl;
+ S.Diag(decl->getLocation(), diag::warn_undefined_internal)
+ << isa<VarDecl>(decl) << decl;
+ S.Diag(i->useLoc, diag::note_used_here);
+ }
+}
+
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
@@ -403,6 +462,8 @@ void Sema::ActOnEndOfTranslationUnit() {
<< DiagD->getDeclName();
}
}
+
+ checkUndefinedInternals(*this);
}
TUScope = 0;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 792eb8af98..df49ad5c9a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9284,6 +9284,9 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
MarkVTableUsed(Loc, MethodDecl->getParent());
}
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ // Recursive functions should be marked when used from another function.
+ if (CurContext == Function) return;
+
// Implicit instantiation of function templates and member functions of
// class templates.
if (Function->isImplicitlyInstantiable()) {
@@ -9312,19 +9315,23 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
else
PendingInstantiations.push_back(std::make_pair(Function, Loc));
}
- } else // Walk redefinitions, as some of them may be instantiable.
+ } else {
+ // Walk redefinitions, as some of them may be instantiable.
for (FunctionDecl::redecl_iterator i(Function->redecls_begin()),
e(Function->redecls_end()); i != e; ++i) {
if (!i->isUsed(false) && i->isImplicitlyInstantiable())
MarkDeclarationReferenced(Loc, *i);
}
+ }
- // FIXME: keep track of references to static functions
-
- // Recursive functions should be marked when used from another function.
- if (CurContext != Function)
- Function->setUsed(true);
+ // Keep track of used but undefined functions.
+ if (!Function->isPure() && !Function->hasBody() &&
+ Function->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+ Function->setUsed(true);
return;
}
@@ -9341,7 +9348,12 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
}
}
- // FIXME: keep track of references to static data?
+ // Keep track of used but undefined variables.
+ if (Var->hasDefinition() == VarDecl::DeclarationOnly
+ && Var->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
D->setUsed(true);
return;