Skip to content

[clang][AST][ASTImporter] improve AST comparasion on VarDecl & GotoStmt #66976

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions clang/lib/AST/ASTStructuralEquivalence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,17 @@ class StmtComparer {

bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }

bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) {
LabelDecl *L1 = S1->getLabel();
LabelDecl *L2 = S2->getLabel();
if (!L1 || !L2)
return L1 == L2;

IdentifierInfo *Name1 = L1->getIdentifier();
IdentifierInfo *Name2 = L2->getIdentifier();
return ::IsStructurallyEquivalent(Name1, Name2);
}

bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) {
return E1->getIdentKind() == E2->getIdentKind();
}
Expand Down Expand Up @@ -1295,6 +1306,22 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
}

static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
VarDecl *D1, VarDecl *D2) {
if (D1->getStorageClass() != D2->getStorageClass())
return false;

IdentifierInfo *Name1 = D1->getIdentifier();
IdentifierInfo *Name2 = D2->getIdentifier();
if (!::IsStructurallyEquivalent(Name1, Name2))
return false;

if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
return false;

return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit());
}

static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
FieldDecl *Field1, FieldDecl *Field2,
QualType Owner2Type) {
Expand Down
77 changes: 75 additions & 2 deletions clang/unittests/AST/StructuralEquivalenceTest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Frontend/ASTUnit.h"
Expand Down Expand Up @@ -1801,10 +1802,10 @@ TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {
TEST_F(StructuralEquivalenceCacheTest, ReturnStmtNonEq) {
auto TU = makeTuDecls(
R"(
bool x(){ return true; }
bool x() { return true; }
)",
R"(
bool x(){ return false; }
bool x() { return false; }
)",
Lang_CXX03);

Expand All @@ -1817,6 +1818,60 @@ TEST_F(StructuralEquivalenceCacheTest, ReturnStmtNonEq) {

}

TEST_F(StructuralEquivalenceCacheTest, VarDeclNoEq) {
auto TU = makeTuDecls(
R"(
int p;
)",
R"(
int q;
)",
Lang_CXX03);

StructuralEquivalenceContext Ctx(
get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);

auto Var = findDeclPair<VarDecl>(TU, varDecl());
EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
}

TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) {
auto TU = makeTuDecls(
R"(
int p;
)",
R"(
static int p;
)",
Lang_CXX03);

StructuralEquivalenceContext Ctx(
get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);

auto Var = findDeclPair<VarDecl>(TU, varDecl());
EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
}

TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) {
auto TU = makeTuDecls(
R"(
int p = 1;
)",
R"(
int p = 2;
)",
Lang_CXX03);

StructuralEquivalenceContext Ctx(
get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);

auto Var = findDeclPair<VarDecl>(TU, varDecl());
EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
}

TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {
auto TU = makeTuDecls(
R"(
Expand Down Expand Up @@ -2320,5 +2375,23 @@ TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookup) {
EXPECT_TRUE(testStructuralMatch(t));
}

TEST_F(StructuralEquivalenceCacheTest, GotoStmtNoEq) {
auto S = makeStmts(
R"(
void foo() {
goto L1;
L1: foo();
}
)",
R"(
void foo() {
goto L2;
L2: foo();
}
)",
Lang_CXX03, gotoStmt());
EXPECT_FALSE(testStructuralMatch(S));
}

} // end namespace ast_matchers
} // end namespace clang