Skip to content

[include-cleaner] Mark RecordDecls referenced in UsingDecls as explicit #106430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 29, 2024

Conversation

kadircet
Copy link
Member

We were reporting ambigious references from using declarations as user
can be depending on different overloads of a function just because they
are visible in the TU.
This doesn't apply to records, or primary templates as declaration being
referenced in such cases is unambigious, the ambiguity applies to
specializations though.

Hence this patch returns an explicit reference to record decls and
primary templates of those.

@llvmbot
Copy link
Member

llvmbot commented Aug 28, 2024

@llvm/pr-subscribers-clang-tools-extra

Author: kadir çetinkaya (kadircet)

Changes

We were reporting ambigious references from using declarations as user
can be depending on different overloads of a function just because they
are visible in the TU.
This doesn't apply to records, or primary templates as declaration being
referenced in such cases is unambigious, the ambiguity applies to
specializations though.

Hence this patch returns an explicit reference to record decls and
primary templates of those.


Full diff: https://github.com/llvm/llvm-project/pull/106430.diff

2 Files Affected:

  • (modified) clang-tools-extra/include-cleaner/lib/WalkAST.cpp (+1-1)
  • (modified) clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp (+8-3)
diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index 598484d09712e5..5e6b862caf0d6c 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -203,7 +203,7 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
   bool VisitUsingDecl(UsingDecl *UD) {
     for (const auto *Shadow : UD->shadows()) {
       auto *TD = Shadow->getTargetDecl();
-      auto IsUsed = TD->isUsed() || TD->isReferenced();
+      auto IsUsed = TD->isUsed() || TD->isReferenced() || !TD->getAsFunction();
       report(UD->getLocation(), TD,
              IsUsed ? RefType::Explicit : RefType::Ambiguous);
 
diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index 6c8eacbff1cea3..9286758cab081c 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -255,7 +255,7 @@ TEST(WalkAST, TemplateSpecializationsFromUsingDecl) {
   // Class templates
   testWalk(R"cpp(
 namespace ns {
-template<class T> class $ambiguous^Z {};      // primary template
+template<class T> class $explicit^Z {};      // primary template
 template<class T> class $ambiguous^Z<T*> {};  // partial specialization
 template<> class $ambiguous^Z<int> {};        // full specialization
 }
@@ -265,7 +265,7 @@ template<> class $ambiguous^Z<int> {};        // full specialization
   // Var templates
   testWalk(R"cpp(
 namespace ns {
-template<class T> T $ambiguous^foo;      // primary template
+template<class T> T $explicit^foo;      // primary template
 template<class T> T $ambiguous^foo<T*>;  // partial specialization
 template<> int* $ambiguous^foo<int>;     // full specialization
 }
@@ -335,7 +335,12 @@ TEST(WalkAST, Using) {
   testWalk(R"cpp(
     namespace ns {
       template<class T>
-      class $ambiguous^Y {};
+      class $explicit^Y {};
+    })cpp",
+           "using ns::^Y;");
+  testWalk(R"cpp(
+    namespace ns {
+      class $explicit^Y {};
     })cpp",
            "using ns::^Y;");
   testWalk(R"cpp(

@@ -203,7 +203,7 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
bool VisitUsingDecl(UsingDecl *UD) {
for (const auto *Shadow : UD->shadows()) {
auto *TD = Shadow->getTargetDecl();
auto IsUsed = TD->isUsed() || TD->isReferenced();
auto IsUsed = TD->isUsed() || TD->isReferenced() || !TD->getAsFunction();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the name IsUsed no longer reflects its purpose. Consider renaming it to something more suitable or inlining it.

Additionally, it would be helpful to add comments to document the intention behind this code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I was actually thinking that usedness is still the right concept here, spelling of the type name in the using declaration is enough to trigger that use for records.

I added comments also along those lines, LMK if it still doesn't resonate with you.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connection between usedness and !TD->getAsFunction() wasn’t immediately obvious to me. With the newly-added comment, it's much clearer now, everything looks good, thanks.

We were reporting ambigious references from using declarations as user
can be depending on different overloads of a function just because they
are visible in the TU.
This doesn't apply to records, or primary templates as declaration being
referenced in such cases is unambigious, the ambiguity applies to
specializations though.

Hence this patch returns an explicit reference to record decls and
primary templates of those.
@kadircet kadircet force-pushed the inc_cleaner_using_records branch from 8969498 to 9a96724 Compare August 29, 2024 08:06
@@ -203,7 +203,7 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
bool VisitUsingDecl(UsingDecl *UD) {
for (const auto *Shadow : UD->shadows()) {
auto *TD = Shadow->getTargetDecl();
auto IsUsed = TD->isUsed() || TD->isReferenced();
auto IsUsed = TD->isUsed() || TD->isReferenced() || !TD->getAsFunction();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connection between usedness and !TD->getAsFunction() wasn’t immediately obvious to me. With the newly-added comment, it's much clearer now, everything looks good, thanks.

@kadircet kadircet merged commit acff429 into llvm:main Aug 29, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants