summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ.Ru <juanruben.segovia@gmail.com>2017-10-01 14:35:16 +0200
committerKim Grasman <kim.grasman@gmail.com>2017-10-04 20:16:37 +0200
commit576e80f7f37ce2daa59120c40f38735b3fbc7422 (patch)
tree8719103a5235d1fd358a5957d8b2df86ffc0f879
parentcd157da809cc50f1ce0b1be0373413ab3b8b64c7 (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.cc20
-rw-r--r--iwyu_output.h2
-rw-r--r--tests/cxx/macro_use_expanded_decl-class.h21
-rw-r--r--tests/cxx/macro_use_expanded_decl-macro.h20
-rw-r--r--tests/cxx/macro_use_expanded_decl.cc46
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 */