From b9725cfb0a50731930a6331beb70f361b4d52a29 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 8 Jan 2013 19:43:34 +0000 Subject: [PATCH] Mark all subsequent decls used. In the source static void f(); static void f(); template static void g() { f(); } static void f() { } void h() { g(); } the call to f refers to the second decl, but it is only marked used at the end of the translation unit during instantiation, after the third f decl has been linked in. With this patch we mark all subsequent decls used, so that it is easy to check if a symbol is used or not. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171888 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.cpp | 6 +----- lib/Sema/SemaExpr.cpp | 13 ++++++++++++- test/SemaCXX/warn-func-not-needed.cpp | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 66861ae663..8f9e1a9a0f 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -328,11 +328,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { /// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector. static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { - // Template instantiation can happen at the end of the translation unit - // and it sets the canonical (first) decl to used. Normal uses set the last - // decl at the time to used and subsequent decl inherit the flag. The net - // result is that we need to check both ends of the decl chain. - if (D->isUsed() || D->getMostRecentDecl()->isUsed()) + if (D->getMostRecentDecl()->isUsed()) return true; if (const FunctionDecl *FD = dyn_cast(D)) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3702aa037c..cc692cda63 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10495,7 +10495,18 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { if (old.isInvalid()) old = Loc; } - Func->setUsed(true); + // Normally the must current decl is marked used while processing the use and + // any subsequent decls are marked used by decl merging. This fails with + // template instantiation since marking can happen at the end of the file + // and, because of the two phase lookup, this function is called with at + // decl in the middle of a decl chain. We loop to maintain the invariant + // that once a decl is used, all decls after it are also used. + for (FunctionDecl *F = Func->getMostRecentDecl();;) { + F->setUsed(true); + if (F == Func) + break; + F = F->getPreviousDecl(); + } } static void diff --git a/test/SemaCXX/warn-func-not-needed.cpp b/test/SemaCXX/warn-func-not-needed.cpp index 0cc639fdd2..d51c173566 100644 --- a/test/SemaCXX/warn-func-not-needed.cpp +++ b/test/SemaCXX/warn-func-not-needed.cpp @@ -28,3 +28,17 @@ namespace test3 { g(); } } + +namespace test4 { + static void f(); + static void f(); + template + static void g() { + f(); + } + static void f() { + } + void h() { + g(); + } +} -- 2.40.0