diff options
author | J.Ru <juanruben.segovia@gmail.com> | 2017-10-01 14:35:16 +0200 |
---|---|---|
committer | Kim Grasman <kim.grasman@gmail.com> | 2017-10-04 20:16:37 +0200 |
commit | 576e80f7f37ce2daa59120c40f38735b3fbc7422 (patch) | |
tree | 8719103a5235d1fd358a5957d8b2df86ffc0f879 | |
parent | cd157da809cc50f1ce0b1be0373413ab3b8b64c7 (diff) |
Always report the expanded location for a decl
In cases where a declaration is generated using a macro, iwyu was
incorrectly suggesting to include the file that defined such macro
instead of the actual location where it was ultimately expanded.
When reporting the declaration for a use, make sure to always refer
to the expansion/instantiation of such declaration. Whether or not
it was part of a macro expansion should be irrelevant for the use.
Fixes #282
-rw-r--r-- | iwyu_output.cc | 20 | ||||
-rw-r--r-- | iwyu_output.h | 2 | ||||
-rw-r--r-- | tests/cxx/macro_use_expanded_decl-class.h | 21 | ||||
-rw-r--r-- | tests/cxx/macro_use_expanded_decl-macro.h | 20 | ||||
-rw-r--r-- | tests/cxx/macro_use_expanded_decl.cc | 46 |
5 files changed, 102 insertions, 7 deletions
diff --git a/iwyu_output.cc b/iwyu_output.cc index 9258dfe..a96be06 100644 --- a/iwyu_output.cc +++ b/iwyu_output.cc @@ -235,8 +235,9 @@ OneUse::OneUse(const NamedDecl* decl, SourceLocation use_loc, : symbol_name_(internal::GetQualifiedNameAsString(decl)), short_symbol_name_(internal::GetShortNameAsString(decl)), decl_(decl), - decl_file_(GetFileEntry(decl)), - decl_filepath_(GetFilePath(decl)), + decl_loc_(GetInstantiationLoc(GetLocation(decl))), + decl_file_(GetFileEntry(decl_loc_)), + decl_filepath_(GetFilePath(decl_file_)), use_loc_(use_loc), use_kind_(use_kind), // full use or fwd-declare use in_cxx_method_body_(in_cxx_method_body), @@ -1120,6 +1121,11 @@ void ProcessFullUse(OneUse* use, // See if we also recorded a use of the parent. const NamedDecl* parent_dfn = GetDefinitionAsWritten(method_dfn->getParent()); + + const FileEntry* decl_file_entry = GetFileEntry(use->decl_loc()); + const FileEntry* parent_file_entry = + GetFileEntry(GetInstantiationLoc(GetLocation(parent_dfn))); + // We want to map the definition-files to their public headers if // they're private headers (so bits/stl_vector.h and // bits/vector.tcc are counted as the "same" file for this test). @@ -1128,16 +1134,16 @@ void ProcessFullUse(OneUse* use, // mapping to choose, and it's important we use the one that iwyu // will pick later). TODO(csilvers): figure out that case too. const IncludePicker& picker = GlobalIncludePicker(); - const vector<string>& method_dfn_files - = picker.GetCandidateHeadersForFilepath(GetFilePath(method_dfn)); - const vector<string>& parent_dfn_files - = picker.GetCandidateHeadersForFilepath(GetFilePath(parent_dfn)); + const vector<string>& method_dfn_files = + picker.GetCandidateHeadersForFilepath(GetFilePath(decl_file_entry)); + const vector<string>& parent_dfn_files = + picker.GetCandidateHeadersForFilepath(GetFilePath(parent_file_entry)); bool same_file; if (method_dfn_files.size() == 1 && parent_dfn_files.size() == 1) { same_file = (method_dfn_files[0] == parent_dfn_files[0]); } else { // Fall back on just checking the filenames: can't figure out public. - same_file = (GetFileEntry(method_dfn) == GetFileEntry(parent_dfn)); + same_file = (decl_file_entry == parent_file_entry); } if (same_file) { VERRS(6) << "Ignoring use of " << use->symbol_name() diff --git a/iwyu_output.h b/iwyu_output.h index 309d1f4..190a0f6 100644 --- a/iwyu_output.h +++ b/iwyu_output.h @@ -68,6 +68,7 @@ class OneUse { const clang::FileEntry* decl_file() const { return decl_file_; } const string& decl_filepath() const { return decl_filepath_; } clang::SourceLocation use_loc() const { return use_loc_; } + clang::SourceLocation decl_loc() const { return decl_loc_; } bool is_full_use() const { return use_kind_ == kFullUse; } bool in_cxx_method_body() const { return in_cxx_method_body_; } const string& comment() const { return comment_; } @@ -100,6 +101,7 @@ class OneUse { string symbol_name_; // the symbol being used string short_symbol_name_; // 'short' form of the symbol being used const clang::NamedDecl* decl_; // decl of the symbol, if we know it + clang::SourceLocation decl_loc_; // where the decl is attributed to live const clang::FileEntry* decl_file_; // file entry where the symbol lives string decl_filepath_; // filepath where the symbol lives clang::SourceLocation use_loc_; // where the symbol is used from diff --git a/tests/cxx/macro_use_expanded_decl-class.h b/tests/cxx/macro_use_expanded_decl-class.h new file mode 100644 index 0000000..df0b325 --- /dev/null +++ b/tests/cxx/macro_use_expanded_decl-class.h @@ -0,0 +1,21 @@ +//===--- macro_use_expanded_decl-class.h - test input file for iwyu -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_USE_EXPANDED_DECL_CLASS_H_ +#define INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_USE_EXPANDED_DECL_CLASS_H_ + +#include "macro_use_expanded_decl-macro.h" + +struct Class { + GEN_METHOD(); +}; + +GEN_CLASS2(); + +#endif //INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_USE_EXPANDED_DECL_CLASS_H_ diff --git a/tests/cxx/macro_use_expanded_decl-macro.h b/tests/cxx/macro_use_expanded_decl-macro.h new file mode 100644 index 0000000..15df144 --- /dev/null +++ b/tests/cxx/macro_use_expanded_decl-macro.h @@ -0,0 +1,20 @@ +//===--- macro_use_expanded_decl-macro.h - test input file for iwyu -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_USE_EXPANDED_DECL_MACRO_H_ +#define INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_USE_EXPANDED_DECL_MACRO_H_ + +#define GEN_METHOD() void gen_method(); +#define CALL_METHOD(a) a.gen_method(); +#define GEN_CLASS2() \ + struct Class2 { \ + GEN_METHOD(); \ + }; + +#endif //INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_USE_EXPANDED_DECL_MACRO_H_ diff --git a/tests/cxx/macro_use_expanded_decl.cc b/tests/cxx/macro_use_expanded_decl.cc new file mode 100644 index 0000000..592420a --- /dev/null +++ b/tests/cxx/macro_use_expanded_decl.cc @@ -0,0 +1,46 @@ +//===--- macro_use_expanded_decl.cc - test input file for iwyu ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "macro_use_expanded_decl-class.h" + +void test() { + Class c; // Class with a method decl generated by a macro + Class2 c2; // Class generated by a macro with a method decl generated by + // nested macro + + // Called directly, already including *-class.h + + c.gen_method(); + c2.gen_method(); + + // Called through a macro, need to include *-macro.h + + // IWYU: CALL_METHOD is...*-macro.h + CALL_METHOD(c) + // IWYU: CALL_METHOD is...*-macro.h + CALL_METHOD(c2) +} + +// Note: gen_method() is not reported as a use for either class because +// of rule B4 (the parent class lives in the same file) This must be true +// no matter if the decl is spelled directly (Class) or through a macro +// defined in a different file (Class2) + +/**** IWYU_SUMMARY + +tests/cxx/macro_use_expanded_decl.cc should add these lines: +#include "macro_use_expanded_decl-macro.h" + +tests/cxx/macro_use_expanded_decl.cc should remove these lines: + +The full include-list for tests/cxx/macro_use_expanded_decl.cc: +#include "macro_use_expanded_decl-class.h" // for Class, Class2 +#include "macro_use_expanded_decl-macro.h" // for CALL_METHOD + +***** IWYU_SUMMARY */ |