diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Decl.cpp | 16 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 61 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 26 |
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; |