usaxena95 created this revision.
usaxena95 added reviewers: massberg, sammccall.
Herald added a subscriber: kadircet.
Herald added a project: All.
usaxena95 requested review of this revision.
Herald added projects: clang, clang-tools-extra.
Herald added a subscriber: cfe-commits.

This is similar to D155858 <https://reviews.llvm.org/D155858> and is probably 
more suited to be a followup to it.

Happy to wait if the mentioned revision is ready to land soon. Otherwise we 
could land this first and fix the include-cleaner bug.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158842

Files:
  clang-tools-extra/include-cleaner/lib/WalkAST.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
  clang/include/clang/AST/RecursiveASTVisitor.h

Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -463,15 +463,13 @@
   bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
   bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
   bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
+  bool TraverseConceptReference(const ConceptReference &C);
 
   bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
 
 private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
-  /// Traverses the qualifier, name and template arguments of a concept
-  /// reference.
-  bool TraverseConceptReferenceHelper(const ConceptReference &C);
 
   // Traverses template parameter lists of either a DeclaratorDecl or TagDecl.
   template <typename T>
@@ -507,7 +505,7 @@
 bool RecursiveASTVisitor<Derived>::TraverseTypeConstraint(
     const TypeConstraint *C) {
   if (!getDerived().shouldVisitImplicitCode()) {
-    TRY_TO(TraverseConceptReferenceHelper(*C));
+    TRY_TO(TraverseConceptReference(*C));
     return true;
   }
   if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) {
@@ -517,7 +515,7 @@
     // if we have an immediately-declared-constraint, otherwise
     // we'll end up visiting the concept and the arguments in
     // the TC twice.
-    TRY_TO(TraverseConceptReferenceHelper(*C));
+    TRY_TO(TraverseConceptReference(*C));
   }
   return true;
 }
@@ -541,7 +539,7 @@
 }
 
 template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseConceptReferenceHelper(
+bool RecursiveASTVisitor<Derived>::TraverseConceptReference(
     const ConceptReference &C) {
   TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc()));
   TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo()));
@@ -2904,7 +2902,7 @@
 })
 
 DEF_TRAVERSE_STMT(ConceptSpecializationExpr,
-                  { TRY_TO(TraverseConceptReferenceHelper(*S)); })
+                  { TRY_TO(TraverseConceptReference(*S)); })
 
 DEF_TRAVERSE_STMT(RequiresExpr, {
   TRY_TO(TraverseDecl(S->getBody()));
Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===================================================================
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -198,6 +198,45 @@
           Pair(Code.point("4"), UnorderedElementsAre(MainFile))));
 }
 
+TEST_F(WalkUsedTest, Concepts) {
+  llvm::Annotations ConceptHdr(guard(R"cpp(
+    template<typename T>
+    concept Foo = true;
+  )cpp"));
+  llvm::Annotations Code(R"cpp(
+    #include "concept.h"
+
+    template<typename T>
+    concept $Bar1^Bar = $Foo1^Foo<T> && true;
+
+    template<$Bar2^Bar T> requires $Bar3^Bar<T> && $Foo2^Foo<T>
+    void $1^func1() {}
+
+    template<$Foo3^Foo T>
+    void $2^func2() requires $Bar4^Bar<T> {}
+  )cpp");
+  Inputs.Code = Code.code();
+  Inputs.ExtraFiles["concept.h"] = ConceptHdr.code();
+  Inputs.ExtraArgs.push_back("--std=c++20");
+  TestAST AST(Inputs);
+  auto &SM = AST.sourceManager();
+  const auto *ConceptHdrFile = SM.getFileManager().getFile("concept.h").get();
+  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+
+  EXPECT_THAT(
+      offsetToProviders(AST),
+      UnorderedElementsAre(
+          Pair(Code.point("Foo1"), UnorderedElementsAre(ConceptHdrFile)),
+          Pair(Code.point("Foo2"), UnorderedElementsAre(ConceptHdrFile)),
+          Pair(Code.point("Foo3"), UnorderedElementsAre(ConceptHdrFile)),
+          Pair(Code.point("Bar1"), UnorderedElementsAre(MainFile)),
+          Pair(Code.point("Bar2"), UnorderedElementsAre(MainFile)),
+          Pair(Code.point("Bar3"), UnorderedElementsAre(MainFile)),
+          Pair(Code.point("Bar4"), UnorderedElementsAre(MainFile)),
+          Pair(Code.point("1"), UnorderedElementsAre(MainFile)),
+          Pair(Code.point("2"), UnorderedElementsAre(MainFile))));
+}
+
 class AnalyzeTest : public testing::Test {
 protected:
   TestInputs Inputs;
@@ -299,7 +338,7 @@
   Results.Unused.push_back(Inc.atLine(4));
 
   EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
-R"cpp(#include "d.h"
+            R"cpp(#include "d.h"
 #include "a.h"
 #include "aa.h"
 #include "ab.h"
@@ -310,7 +349,7 @@
   Results.Missing.push_back("\"d.h\"");
   Code = R"cpp(#include "a.h")cpp";
   EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
-R"cpp(#include "d.h"
+            R"cpp(#include "d.h"
 #include "a.h")cpp");
 }
 
Index: clang-tools-extra/include-cleaner/lib/WalkAST.cpp
===================================================================
--- clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -232,6 +232,15 @@
     return true;
   }
 
+  bool VisitConceptDecl(ConceptDecl *CD) {
+    report(CD->getLocation(), CD);
+    return true;
+  }
+
+  bool TraverseConceptReference(const ConceptReference &C) {
+    report(C.getConceptNameLoc(), C.getFoundDecl());
+    return RecursiveASTVisitor::TraverseConceptReference(C);
+  }
   // Report a reference from explicit specializations to the specialized
   // template. Implicit ones are filtered out by RAV and explicit instantiations
   // are already traversed through typelocs.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to