[clang] [Clang][ASTMatcher] Improve matching isDerivedFrom base in case of multi aliases exists (PR #126793)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 11 12:38:41 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/126793.diff
2 Files Affected:
- (modified) clang/lib/ASTMatchers/ASTMatchFinder.cpp (+21)
- (modified) clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (+17)
``````````diff
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(
``````````
</details>
https://github.com/llvm/llvm-project/pull/126793
More information about the cfe-commits
mailing list