-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang][ASTMatcher] Improve matching isDerivedFrom base in case of multi aliases exists #126793
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
[Clang][ASTMatcher] Improve matching isDerivedFrom base in case of multi aliases exists #126793
Conversation
@llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesPreviously in case of multiable aliases exists for the same base we just accept the first one llvm-project/clang/lib/ASTMatchers/ASTMatchFinder.cpp Lines 1290 to 1297 in 2cf6663
For example
But if we changed the order now it will point to the right one
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:
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(
|
This is a bit more in the weeds of AST matchers internals than what I'm familiar with, so I've added some other reviewers who have made or reviewed more extensive changes to this code based on code history. |
Please take a look when you have time @AaronBallman @alexfh @steveire |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but you should add a release note to clang/docs/ReleaseNotes.rst
so users know about the change in behavior.
bf17eb2
to
08d0a78
Compare
Thank you, I added a release note, once you confirm it's approved I can land after CI is green |
@AaronBallman If releasenote is okey, i can merge now :D |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a minor rewording, feel free to land once you've made the changes.
clang/docs/ReleaseNotes.rst
Outdated
@@ -361,6 +361,8 @@ Fixed Point Support in Clang | |||
AST Matchers | |||
------------ | |||
|
|||
- Ensure ``isDerivedFrom`` is matching the correct base in case of more than one aliases exists. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Ensure ``isDerivedFrom`` is matching the correct base in case of more than one aliases exists. | |
- Ensure ``isDerivedFrom`` matches the correct base in case more than one alias exists. |
Minor rewording
…lti aliases exists (llvm#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: llvm#126498
Previously in case of multiable aliases exists for the same base we just accept the first one
llvm-project/clang/lib/ASTMatchers/ASTMatchFinder.cpp
Lines 1290 to 1297 in 2cf6663
For example
cxxRecordDecl(isDerivedFrom(decl().bind("typedef")))
typedef will be bonded toUnusedTypedef
But if we changed the order now it will point to the right one
cxxRecordDecl(isDerivedFrom(decl().bind("typedef")))
typedef will be bonded toBase
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