Skip to content

Commit c017cdf

Browse files
authored
[Clang][ASTMatcher] Improve matching isDerivedFrom base in case of multi 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
1 parent 44c6a23 commit c017cdf

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ Fixed Point Support in Clang
361361
AST Matchers
362362
------------
363363

364+
- Ensure ``isDerivedFrom`` matches the correct base in case more than one alias exists.
365+
364366
clang-format
365367
------------
366368

clang/lib/ASTMatchers/ASTMatchFinder.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,27 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
12871287
auto Aliases = TypeAliases.find(CanonicalType);
12881288
if (Aliases == TypeAliases.end())
12891289
return false;
1290+
1291+
if (const auto *ElaboratedTypeNode =
1292+
llvm::dyn_cast<ElaboratedType>(TypeNode)) {
1293+
if (ElaboratedTypeNode->isSugared() && Aliases->second.size() > 1) {
1294+
const auto &DesugaredTypeName =
1295+
ElaboratedTypeNode->desugar().getAsString();
1296+
1297+
for (const TypedefNameDecl *Alias : Aliases->second) {
1298+
if (Alias->getName() != DesugaredTypeName) {
1299+
continue;
1300+
}
1301+
1302+
BoundNodesTreeBuilder Result(*Builder);
1303+
if (Matcher.matches(*Alias, this, &Result)) {
1304+
*Builder = std::move(Result);
1305+
return true;
1306+
}
1307+
}
1308+
}
1309+
}
1310+
12901311
for (const TypedefNameDecl *Alias : Aliases->second) {
12911312
BoundNodesTreeBuilder Result(*Builder);
12921313
if (Matcher.matches(*Alias, this, &Result)) {

clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,23 @@ TEST_P(ASTMatchersTest, IsDerivedFrom_EmptyName) {
11671167
EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isSameOrDerivedFrom(""))));
11681168
}
11691169

1170+
TEST_P(ASTMatchersTest, IsDerivedFrom_ElaboratedType) {
1171+
if (!GetParam().isCXX()) {
1172+
return;
1173+
}
1174+
1175+
DeclarationMatcher IsDerivenFromBase =
1176+
cxxRecordDecl(isDerivedFrom(decl().bind("typedef")));
1177+
1178+
EXPECT_TRUE(matchAndVerifyResultTrue(
1179+
"struct AnInterface {};"
1180+
"typedef AnInterface UnusedTypedef;"
1181+
"typedef AnInterface Base;"
1182+
"class AClass : public Base {};",
1183+
IsDerivenFromBase,
1184+
std::make_unique<VerifyIdIsBoundTo<TypedefDecl>>("typedef", "Base")));
1185+
}
1186+
11701187
TEST_P(ASTMatchersTest, IsDerivedFrom_ObjC) {
11711188
DeclarationMatcher IsDerivedFromX = objcInterfaceDecl(isDerivedFrom("X"));
11721189
EXPECT_TRUE(

0 commit comments

Comments
 (0)