[clang] c017cdf - [Clang][ASTMatcher] Improve matching isDerivedFrom base in case of multi aliases exists (#126793)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 5 12:32:28 PST 2025


Author: Amr Hesham
Date: 2025-03-05T21:32:24+01:00
New Revision: c017cdf0714afcccca3338529134f3792d9287f6

URL: https://github.com/llvm/llvm-project/commit/c017cdf0714afcccca3338529134f3792d9287f6
DIFF: https://github.com/llvm/llvm-project/commit/c017cdf0714afcccca3338529134f3792d9287f6.diff

LOG: [Clang][ASTMatcher] Improve matching isDerivedFrom base in case of multi aliases exists (#126793)

Previously in case of multiable aliases exists for the same base we just
accept the first one


https://github.com/llvm/llvm-project/blob/2cf6663d3c86b065edeb693815e6a4b325045cc2/clang/lib/ASTMatchers/ASTMatchFinder.cpp#L1290-L1297

For example

```
struct AnInterface {};
typedef AnInterface UnusedTypedef;
typedef AnInterface Base;
class AClass : public Base {};
```

`cxxRecordDecl(isDerivedFrom(decl().bind("typedef")))` typedef will be
bonded to `UnusedTypedef`

But if we changed the order now it will point to the right one

```
struct AnInterface {};
typedef AnInterface Base;
typedef AnInterface UnusedTypedef;
class AClass : public Base {};
```

`cxxRecordDecl(isDerivedFrom(decl().bind("typedef")))` typedef will be
bonded to `Base`

This PR improve the matcher to prioritise the alias that has same
desugared name as the base, if not then just accept the first one.

Fixes: #126498

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/ASTMatchers/ASTMatchFinder.cpp
    clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 35efa2ca4aa93..32db3fe5740ed 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -361,6 +361,8 @@ Fixed Point Support in Clang
 AST Matchers
 ------------
 
+- Ensure ``isDerivedFrom`` matches the correct base in case more than one alias exists.
+
 clang-format
 ------------
 

diff  --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 3d01a70395a9b..e9ec7eff1e0ab 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1287,6 +1287,27 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
     auto Aliases = TypeAliases.find(CanonicalType);
     if (Aliases == TypeAliases.end())
       return false;
+
+    if (const auto *ElaboratedTypeNode =
+            llvm::dyn_cast<ElaboratedType>(TypeNode)) {
+      if (ElaboratedTypeNode->isSugared() && Aliases->second.size() > 1) {
+        const auto &DesugaredTypeName =
+            ElaboratedTypeNode->desugar().getAsString();
+
+        for (const TypedefNameDecl *Alias : Aliases->second) {
+          if (Alias->getName() != DesugaredTypeName) {
+            continue;
+          }
+
+          BoundNodesTreeBuilder Result(*Builder);
+          if (Matcher.matches(*Alias, this, &Result)) {
+            *Builder = std::move(Result);
+            return true;
+          }
+        }
+      }
+    }
+
     for (const TypedefNameDecl *Alias : Aliases->second) {
       BoundNodesTreeBuilder Result(*Builder);
       if (Matcher.matches(*Alias, this, &Result)) {

diff  --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 5e1c12ba26d87..4e6baedae2be5 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1167,6 +1167,23 @@ TEST_P(ASTMatchersTest, IsDerivedFrom_EmptyName) {
   EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isSameOrDerivedFrom(""))));
 }
 
+TEST_P(ASTMatchersTest, IsDerivedFrom_ElaboratedType) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+
+  DeclarationMatcher IsDerivenFromBase =
+      cxxRecordDecl(isDerivedFrom(decl().bind("typedef")));
+
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "struct AnInterface {};"
+      "typedef AnInterface UnusedTypedef;"
+      "typedef AnInterface Base;"
+      "class AClass : public Base {};",
+      IsDerivenFromBase,
+      std::make_unique<VerifyIdIsBoundTo<TypedefDecl>>("typedef", "Base")));
+}
+
 TEST_P(ASTMatchersTest, IsDerivedFrom_ObjC) {
   DeclarationMatcher IsDerivedFromX = objcInterfaceDecl(isDerivedFrom("X"));
   EXPECT_TRUE(


        


More information about the cfe-commits mailing list