From 27da44e009660d8efc9726b1a4d80d8f9f063539 Mon Sep 17 00:00:00 2001 From: "J.Ru" Date: Thu, 25 Oct 2018 08:42:17 +0200 Subject: [PATCH] Introduce an extra use flag UF_ExplicitInstantiation To signal that the use refers to an explicit instantiation, for which the "canonical" decl is not suitable. Also, since it is meant to be used in a specific context, the ReportDeclUse prototype has been adapted to take optional extra flags as an additional input. --- iwyu.cc | 26 +++++++++++++++----------- iwyu_output.cc | 32 ++++++++++++++++++++------------ iwyu_output.h | 1 + iwyu_use_flags.h | 6 +++--- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/iwyu.cc b/iwyu.cc index a8cf92d..f5cfa5f 100644 --- a/iwyu.cc +++ b/iwyu.cc @@ -109,6 +109,7 @@ #include "iwyu_location_util.h" #include "iwyu_output.h" #include "iwyu_path_util.h" +#include "iwyu_use_flags.h" // This is needed for // preprocessor_info().PublicHeaderIntendsToProvide(). Somehow IWYU // removes it mistakenly. @@ -1632,12 +1633,13 @@ class IwyuBaseAstVisitor : public BaseAstVisitor { // Checkers, that tell iwyu_output about uses of symbols. // We let, but don't require, subclasses to override these. - // The comment, if not nullptr, is extra text that is included along - // with the warning message that iwyu emits. + // The comment, if not nullptr, is extra text that is included along with + // the warning message that iwyu emits. The extra use flags is optional + // info that can be assigned to the use (see the UF_* constants) virtual void ReportDeclUse(SourceLocation used_loc, const NamedDecl* used_decl, - const char* comment = nullptr) { - + const char* comment = nullptr, + UseFlags extra_use_flags = 0) { const NamedDecl* target_decl = used_decl; // Sometimes a shadow decl comes between us and the 'real' decl. @@ -1649,12 +1651,14 @@ class IwyuBaseAstVisitor : public BaseAstVisitor { if (CanIgnoreDecl(target_decl)) return; + const UseFlags use_flags = + ComputeUseFlags(current_ast_node()) | extra_use_flags; + // Canonicalize the use location and report the use. used_loc = GetCanonicalUseLocation(used_loc, target_decl); const FileEntry* used_in = GetFileEntry(used_loc); preprocessor_info().FileInfoFor(used_in)->ReportFullSymbolUse( - used_loc, target_decl, ComputeUseFlags(current_ast_node()), - comment); + used_loc, target_decl, use_flags, comment); // Sometimes using a decl drags in a few other uses as well: @@ -1672,8 +1676,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor { = GetUsingDeclarationOf(used_decl, GetDeclContext(current_ast_node()))) { preprocessor_info().FileInfoFor(used_in)->ReportUsingDeclUse( - used_loc, using_decl, ComputeUseFlags(current_ast_node()), - "(for using decl)"); + used_loc, using_decl, use_flags, "(for using decl)"); } // For typedefs, the user of the type is sometimes the one @@ -2910,19 +2913,20 @@ class InstantiatedTemplateVisitor // (if templates call other templates, we have to find the right // template). void ReportDeclUse(SourceLocation used_loc, const NamedDecl* decl, - const char* comment = nullptr) override { + const char* comment = nullptr, + UseFlags extra_use_flags = 0) override { const SourceLocation actual_used_loc = GetLocOfTemplateThatProvides(decl); if (actual_used_loc.isValid()) { // If a template is responsible for this decl, then we don't add // it to the cache; the cache is only for decls that the // original caller is responsible for. - Base::ReportDeclUse(actual_used_loc, decl, comment); + Base::ReportDeclUse(actual_used_loc, decl, comment, extra_use_flags); } else { // Let all the currently active types and decls know about this // report, so they can update their cache entries. for (CacheStoringScope* storer : cache_storers_) storer->NoteReportedDecl(decl); - Base::ReportDeclUse(caller_loc(), decl, comment); + Base::ReportDeclUse(caller_loc(), decl, comment, extra_use_flags); } } diff --git a/iwyu_output.cc b/iwyu_output.cc index 126aa50..797c4d3 100644 --- a/iwyu_output.cc +++ b/iwyu_output.cc @@ -237,12 +237,12 @@ string GetShortNameAsString(const clang::NamedDecl* named_decl) { // Holds information about a single full or fwd-decl use of a symbol. OneUse::OneUse(const NamedDecl* decl, SourceLocation use_loc, - OneUse::UseKind use_kind, UseFlags flags, - const char* comment) + SourceLocation decl_loc, OneUse::UseKind use_kind, + UseFlags flags, const char* comment) : symbol_name_(internal::GetQualifiedNameAsString(decl)), short_symbol_name_(internal::GetShortNameAsString(decl)), decl_(decl), - decl_loc_(GetInstantiationLoc(GetLocation(decl))), + decl_loc_(GetInstantiationLoc(decl_loc)), decl_file_(GetFileEntry(decl_loc_)), decl_filepath_(GetFilePath(decl_file_)), use_loc_(use_loc), @@ -577,15 +577,23 @@ void IwyuFileInfo::ReportFullSymbolUse(SourceLocation use_loc, UseFlags flags, const char* comment) { if (decl) { - // Since we need the full symbol, we need the decl's definition-site. - // But only if we're not defining the function, in which case we want to use - // all its preceding declarations, and not try to canonicalize. - if (!(flags & UF_FunctionDfn)) { - decl = GetDefinitionAsWritten(decl); + const NamedDecl* report_decl; + SourceLocation report_decl_loc; + + if ((flags & (UF_FunctionDfn | UF_ExplicitInstantiation)) == 0) { + // Since we need the full symbol, we need the decl's definition-site too. + // Also, by default we canonicalize the location, using GetLocation. + report_decl = GetDefinitionAsWritten(decl); + report_decl_loc = GetLocation(report_decl); + } else { + // However, if we're defining the function or we are targeting an explicit + // instantiation, we want to use it as-is and not try to canonicalize at all. + report_decl = decl; + report_decl_loc = decl->getLocation(); } - symbol_uses_.push_back(OneUse(decl, use_loc, OneUse::kFullUse, - flags, comment)); + symbol_uses_.push_back(OneUse(report_decl, use_loc, report_decl_loc, + OneUse::kFullUse, flags, comment)); LogSymbolUse("Marked full-info use of decl", symbol_uses_.back()); } } @@ -630,8 +638,8 @@ void IwyuFileInfo::ReportForwardDeclareUse(SourceLocation use_loc, // combines friend decls with true forward-declare decls. If that // happened here, replace the friend with a real fwd decl. decl = GetNonfriendClassRedecl(decl); - symbol_uses_.push_back(OneUse(decl, use_loc, OneUse::kForwardDeclareUse, - flags, comment)); + symbol_uses_.push_back(OneUse(decl, use_loc, GetLocation(decl), + OneUse::kForwardDeclareUse, flags, comment)); LogSymbolUse("Marked fwd-decl use of decl", symbol_uses_.back()); } diff --git a/iwyu_output.h b/iwyu_output.h index 3aed01d..719f821 100644 --- a/iwyu_output.h +++ b/iwyu_output.h @@ -50,6 +50,7 @@ class OneUse { OneUse(const clang::NamedDecl* decl, clang::SourceLocation use_loc, + clang::SourceLocation decl_loc, UseKind use_kind, UseFlags flags, const char* comment); diff --git a/iwyu_use_flags.h b/iwyu_use_flags.h index 4a2e749..39cac34 100644 --- a/iwyu_use_flags.h +++ b/iwyu_use_flags.h @@ -16,9 +16,9 @@ namespace include_what_you_use { typedef unsigned UseFlags; const UseFlags UF_None = 0; -const UseFlags UF_InCxxMethodBody = 1; // use is inside a C++ method body -const UseFlags UF_FunctionDfn = 2; // use is a function being defined - +const UseFlags UF_InCxxMethodBody = 1; // use is inside a C++ method body +const UseFlags UF_FunctionDfn = 2; // use is a function being defined +const UseFlags UF_ExplicitInstantiation = 4; // use targets an explicit instantiation } #endif