-
Notifications
You must be signed in to change notification settings - Fork 12.4k
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][index] Fix processing of CompoundAssignOperator at setting up reference roles #69370
[clang][index] Fix processing of CompoundAssignOperator at setting up reference roles #69370
Conversation
… reference roles Without this patch in expressions like `foo += 1` reference `foo` has no read and write roles. This happens because `CompoundAssignOperator` is also a `BinaryOperator`, thus handling `CompoindAssignOperator` in `else` branch is a dead code.
@llvm/pr-subscribers-clang Author: Aleksandr Platonov (ArcsinX) ChangesWithout this patch in expressions like This happens because Full diff: https://github.com/llvm/llvm-project/pull/69370.diff 2 Files Affected:
diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
index e88f321f18a7129..08136baa5d408e9 100644
--- a/clang/lib/Index/IndexBody.cpp
+++ b/clang/lib/Index/IndexBody.cpp
@@ -77,9 +77,15 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
const Stmt *Parent = *It;
if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
- if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
- Roles |= (unsigned)SymbolRole::Write;
-
+ if (BO->getOpcode() == BO_Assign) {
+ if (BO->getLHS()->IgnoreParenCasts() == E)
+ Roles |= (unsigned)SymbolRole::Write;
+ } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
+ if (CA->getLHS()->IgnoreParenCasts() == E) {
+ Roles |= (unsigned)SymbolRole::Read;
+ Roles |= (unsigned)SymbolRole::Write;
+ }
+ }
} else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
if (UO->isIncrementDecrementOp()) {
Roles |= (unsigned)SymbolRole::Read;
@@ -88,12 +94,6 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
Roles |= (unsigned)SymbolRole::AddressOf;
}
- } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
- if (CA->getLHS()->IgnoreParenCasts() == E) {
- Roles |= (unsigned)SymbolRole::Read;
- Roles |= (unsigned)SymbolRole::Write;
- }
-
} else if (auto CE = dyn_cast<CallExpr>(Parent)) {
if (CE->getCallee()->IgnoreParenCasts() == E) {
addCallRole(Roles, Relations);
diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp
index 4d19f47283c2853..8e9a1c6bf88245c 100644
--- a/clang/unittests/Index/IndexTests.cpp
+++ b/clang/unittests/Index/IndexTests.cpp
@@ -428,6 +428,31 @@ TEST(IndexTest, NonTypeTemplateParameter) {
WrittenAt(Position(3, 15)))));
}
+TEST(IndexTest, ReadWriteRoles) {
+ std::string Code = R"cpp(
+ int main() {
+ int foo = 0;
+ foo = 2;
+ foo += 1;
+ int bar = foo;
+ }
+ )cpp";
+ auto Index = std::make_shared<Indexer>();
+ IndexingOptions Opts;
+ Opts.IndexFunctionLocals = true;
+ tooling::runToolOnCode(std::make_unique<IndexAction>(Index, Opts), Code);
+ EXPECT_THAT(
+ Index->Symbols,
+ AllOf(Contains(AllOf(QName("foo"), HasRole(SymbolRole::Write),
+ WrittenAt(Position(4, 7)))),
+ Contains(AllOf(QName("foo"),
+ HasRole(static_cast<unsigned>(SymbolRole::Read) |
+ static_cast<unsigned>(SymbolRole::Write)),
+ WrittenAt(Position(5, 7)))),
+ Contains(AllOf(QName("foo"), HasRole(SymbolRole::Read),
+ WrittenAt(Position(6, 17))))));
+}
+
} // namespace
} // namespace index
} // namespace clang
|
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.
good catch.
Roles |= (unsigned)SymbolRole::Write; | ||
|
||
if (BO->getOpcode() == BO_Assign) { | ||
if (BO->getLHS()->IgnoreParenCasts() == E) |
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.
nit: consider inlining this if
to the one above (like the original code) to the code less nested.
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.
I split this if
to avoid this check else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent))
if BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() != E
I.e. if BO->getOpcode() == BO_Assign
then Parent
is not a CompoundAssignOperator
and we don't need to check this
Without this patch in expressions like
foo += 1
referencefoo
has no read and write roles.This happens because
CompoundAssignOperator
is also aBinaryOperator
, thus handlingCompoindAssignOperator
inelse
branch is a dead code.