VitaNuo created this revision.
Herald added a subscriber: kadircet.
Herald added a project: All.
VitaNuo requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Use expansion locations for target symbol decls when finding headers for macros.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139716

Files:
  clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
  clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp

Index: clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
===================================================================
--- clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
@@ -7,11 +7,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "AnalysisInternal.h"
+#include "clang-include-cleaner/Analysis.h"
 #include "clang-include-cleaner/Record.h"
+#include "clang-include-cleaner/Types.h"
 #include "clang/Basic/FileEntry.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Testing/TestAST.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Testing/Support/Annotations.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <memory>
@@ -31,7 +36,7 @@
   std::unique_ptr<TestAST> AST;
   FindHeadersTest() {
     Inputs.MakeAction = [this] {
-      struct Hook : public PreprocessOnlyAction {
+      struct Hook : public SyntaxOnlyAction {
       public:
         Hook(PragmaIncludes *Out) : Out(Out) {}
         bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
@@ -153,5 +158,121 @@
                                    physicalHeader("exporter.h")));
 }
 
+TEST_F(FindHeadersTest, TargetIsArgumentExpandedFromMacroInHeader) {
+  llvm::Annotations MainFile(R"cpp(
+    #include "declare.h"
+    Foo foo;
+  )cpp");
+  Inputs.Code = MainFile.code();
+  Inputs.ExtraFiles["declare.h"] = R"cpp(
+    #include "macro.h"
+    DEFINE_CLASS(Foo)
+  )cpp";
+  Inputs.ExtraFiles["macro.h"] = R"cpp(
+    #define DEFINE_CLASS(name) class name {};
+  )cpp";
+
+  buildAST();
+  llvm::SmallVector<Decl *> TopLevelDecls;
+  for (Decl *D : AST->context().getTranslationUnitDecl()->decls()) {
+    if (!AST->sourceManager().isWrittenInMainFile(
+            AST->sourceManager().getExpansionLoc(D->getLocation())))
+      continue;
+    TopLevelDecls.emplace_back(D);
+  }
+  EXPECT_EQ(TopLevelDecls.size(), 1u);
+
+  std::vector<Header> Headers;
+  walkUsed(
+      TopLevelDecls, {}, nullptr, AST->sourceManager(),
+      [&Headers](const SymbolReference &Ref, llvm::ArrayRef<Header> Providers) {
+        if (!llvm::isa<RecordDecl>(Ref.Target.declaration()))
+          return;
+        for (const Header &Header : Providers)
+          Headers.push_back(Header);
+      });
+
+  EXPECT_EQ(Headers.size(), 1u);
+  EXPECT_THAT(Headers, UnorderedElementsAre(physicalHeader("declare.h")));
+}
+
+TEST_F(FindHeadersTest, TargetIsBodyExpandedFromMacroInHeader) {
+  llvm::Annotations MainFile(R"cpp(
+    #include "declare.h"
+    void test(Foo foo);
+  )cpp");
+  Inputs.Code = MainFile.code();
+  Inputs.ExtraFiles["declare.h"] = R"cpp(
+    #include "macro.h"
+    DEFINE_Foo
+  )cpp";
+  Inputs.ExtraFiles["macro.h"] = R"cpp(
+    #define DEFINE_Foo class Foo {};
+  )cpp";
+
+  buildAST();
+  llvm::SmallVector<Decl *> TopLevelDecls;
+  for (Decl *D : AST->context().getTranslationUnitDecl()->decls()) {
+    if (!AST->sourceManager().isWrittenInMainFile(
+            AST->sourceManager().getExpansionLoc(D->getLocation())))
+      continue;
+    TopLevelDecls.emplace_back(D);
+  }
+  EXPECT_EQ(TopLevelDecls.size(), 1u);
+
+  std::vector<Header> Headers;
+  walkUsed(
+      TopLevelDecls, {}, nullptr, AST->sourceManager(),
+      [&Headers](const SymbolReference &Ref, llvm::ArrayRef<Header> Providers) {
+        if (!llvm::isa<RecordDecl>(Ref.Target.declaration()))
+          return;
+        for (const Header &Header : Providers)
+          Headers.push_back(Header);
+      });
+
+  EXPECT_EQ(Headers.size(), 1u);
+  EXPECT_THAT(Headers, UnorderedElementsAre(physicalHeader("declare.h")));
+}
+
+TEST_F(FindHeadersTest, TargetIsTokenPasted) {
+  llvm::Annotations MainFile(R"cpp(
+    #include "declare.h"
+    void foo() {
+      FLAG_foo;
+    }
+  )cpp");
+  Inputs.Code = MainFile.code();
+  Inputs.ExtraFiles["declare.h"] = R"cpp(
+    #include "flag.h"
+    DECLARE_FLAGS(foo);
+  )cpp";
+  Inputs.ExtraFiles["flag.h"] = R"cpp(
+    #define DECLARE_FLAGS(name) extern int FLAG_##name
+  )cpp";
+
+  buildAST();
+  llvm::SmallVector<Decl *> TopLevelDecls;
+  for (Decl *D : AST->context().getTranslationUnitDecl()->decls()) {
+    if (!AST->sourceManager().isWrittenInMainFile(
+            AST->sourceManager().getExpansionLoc(D->getLocation())))
+      continue;
+    TopLevelDecls.emplace_back(D);
+  }
+  EXPECT_EQ(TopLevelDecls.size(), 1u);
+
+  std::vector<Header> Headers;
+  walkUsed(
+      TopLevelDecls, {}, nullptr, AST->sourceManager(),
+      [&Headers](const SymbolReference &Ref, llvm::ArrayRef<Header> Providers) {
+        if (!llvm::isa<VarDecl>(Ref.Target.declaration()))
+          return;
+        for (const Header &Header : Providers)
+          Headers.push_back(Header);
+      });
+
+  EXPECT_EQ(Headers.size(), 1u);
+  EXPECT_THAT(Headers, UnorderedElementsAre(physicalHeader("declare.h")));
+}
+
 } // namespace
 } // namespace clang::include_cleaner
\ No newline at end of file
Index: clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
===================================================================
--- clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
+++ clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
@@ -19,7 +19,7 @@
   switch (Loc.kind()) {
   case SymbolLocation::Physical: {
     // FIXME: Handle macro locations.
-    FileID FID = SM.getFileID(Loc.physical());
+    FileID FID = SM.getFileID(SM.getExpansionLoc(Loc.physical()));
     const FileEntry *FE = SM.getFileEntryForID(FID);
     if (!PI) {
       return FE ? llvm::SmallVector<Header>{Header(FE)}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to