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.
This commit is contained in:
J.Ru 2018-10-25 08:42:17 +02:00
parent 0d0832fee7
commit 27da44e009
4 changed files with 39 additions and 26 deletions

26
iwyu.cc
View File

@ -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<Derived> {
// 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<Derived> {
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<Derived> {
= 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);
}
}

View File

@ -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());
}

View File

@ -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);

View File

@ -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