Skip to content
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

hasAnyArgument() spuriously ignores match #75754

Open
xb8g2pw0 opened this issue Dec 17, 2023 · 17 comments · May be fixed by #89509 or #89553
Open

hasAnyArgument() spuriously ignores match #75754

xb8g2pw0 opened this issue Dec 17, 2023 · 17 comments · May be fixed by #89509 or #89553
Assignees
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang-query confirmed Verified by a second party good first issue https://github.com/llvm/llvm-project/contribute

Comments

@xb8g2pw0
Copy link

hasAnyArgument() spuriously ignores a match with the program:

void foo (void *, void *);

struct S {
};

void f() {
   S s;
   foo(&s, &s);
}

and the query:

m callExpr(hasAnyArgument(hasType(asString("S *"))))
0 matches. 

However, the query:

m callExpr(hasArgument(0,hasType(asString("S *"))))

returns the expected result:

...clang_ast_bug_2.cpp:10:2: note: "root" binds here
 10 |         foo(&s, &s);
      |         ^~~~~~~~~~~
1 match.

I am using clang-query 17.0.2 built, I believe, by Mozilla.

@danix800
Copy link
Member

hasArgument() ignores any implicit casts & parenthesis around the argument via an extra Expr::IgnoreParenImpCasts(), which I think is not necessary, while hasAnyArgument() does not ignore anything.

So if you want hasAnyArgument() to work on this example, use m callExpr(hasAnyArgument( ignoringParenImpCasts(hasType(asString("S *"))))), and an extra ignoringParenImpCasts():

m callExpr(hasAnyArgument(ignoringParenImpCasts(hasType(asString("S *")))))

Match #1:

...test.cpp:8:4: note: "root" binds here
   foo(&s, &s);
   ^~~~~~~~~~~
1 match.

hasArgument() might need to be fixed but I'm afraid that would break a lot of clients.

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed new issue labels Dec 18, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 18, 2023

@llvm/issue-subscribers-clang-frontend

Author: None (xb8g2pw0)

`hasAnyArgument()` spuriously ignores a match with the program:
void foo (void *, void *);

struct S {
};

void f() {
   S s;
   foo(&s, &s);
}

and the query:

m callExpr(hasAnyArgument(hasType(asString("S *"))))
0 matches. 

However, the query:

m callExpr(hasArgument(0,hasType(asString("S *"))))

returns the expected result:

...clang_ast_bug_2.cpp:10:2: note: "root" binds here
 10 |         foo(&s, &s);
      |         ^~~~~~~~~~~
1 match.

I am using clang-query 17.0.2 built, I believe, by Mozilla.

@llvmbot
Copy link
Collaborator

llvmbot commented Dec 18, 2023

@llvm/issue-subscribers-clang-query

Author: None (xb8g2pw0)

`hasAnyArgument()` spuriously ignores a match with the program:
void foo (void *, void *);

struct S {
};

void f() {
   S s;
   foo(&s, &s);
}

and the query:

m callExpr(hasAnyArgument(hasType(asString("S *"))))
0 matches. 

However, the query:

m callExpr(hasArgument(0,hasType(asString("S *"))))

returns the expected result:

...clang_ast_bug_2.cpp:10:2: note: "root" binds here
 10 |         foo(&s, &s);
      |         ^~~~~~~~~~~
1 match.

I am using clang-query 17.0.2 built, I believe, by Mozilla.

@xb8g2pw0
Copy link
Author

Thanks for the info. Probably this should be considered a documentation bug? https://clang.llvm.org/docs/LibASTMatchersReference.html does not describe this difference between hasArgument() and hasAnyArgument().

@AaronBallman AaronBallman added the confirmed Verified by a second party label Jan 11, 2024
@AaronBallman
Copy link
Collaborator

I think it's a functionality bug and not a documentation bug. The intent behind hasArgument and hasAnyArgument is that hasArgument cares about the position of the argument and hasAnyArgument does not. I don't think it should have different behavior regarding implicit AST nodes.

@AaronBallman AaronBallman added the good first issue https://github.com/llvm/llvm-project/contribute label Jan 11, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 11, 2024

Hi!

This issue may be a good introductory issue for people new to working on LLVM. If you would like to work on this issue, your first steps are:

  1. In the comments of the issue, request for it to be assigned to you.
  2. Fix the issue locally.
  3. Run the test suite locally. Remember that the subdirectories under test/ create fine-grained testing targets, so you can e.g. use make check-clang-ast to only run Clang's AST tests.
  4. Create a Git commit.
  5. Run git clang-format HEAD~1 to format your changes.
  6. Open a pull request to the upstream repository on GitHub. Detailed instructions can be found in GitHub's documentation.

If you have any further questions about this issue, don't hesitate to ask via a comment in the thread below.

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 11, 2024

@llvm/issue-subscribers-good-first-issue

Author: None (xb8g2pw0)

`hasAnyArgument()` spuriously ignores a match with the program:
void foo (void *, void *);

struct S {
};

void f() {
   S s;
   foo(&s, &s);
}

and the query:

m callExpr(hasAnyArgument(hasType(asString("S *"))))
0 matches. 

However, the query:

m callExpr(hasArgument(0,hasType(asString("S *"))))

returns the expected result:

...clang_ast_bug_2.cpp:10:2: note: "root" binds here
 10 |         foo(&s, &s);
      |         ^~~~~~~~~~~
1 match.

I am using clang-query 17.0.2 built, I believe, by Mozilla.

@AaronBallman
Copy link
Collaborator

I'm marking this as a good first issue because I think the correct behavior is to not ignore implicit AST nodes in hasArgument. We have the TK_IgnoreUnlessSpelledInSource traversal kind for when the user wants to silently skip implicit nodes.

Note, this may cause some fallout that makes this not quite a good first issue because we may have clang-tidy checks that rely on ignoring the implicit nodes. So the fix may be somewhat more involved due to needing to also repair problems with clang-tidy checks.

CC @PiotrZSL @carlosgalvezp @njames93 @LegalizeAdulthood @sam-mccall for extra opinions and thoughts.

@LegalizeAdulthood
Copy link
Contributor

I say go for it. If anyone fixing this gets weird fallout in clang-tidy, we can help out.

@Rajveer100
Copy link
Contributor

@AaronBallman @LegalizeAdulthood
The issue looks clear to me, could you provide a comprehensive insight from your end to get me going?

@11happy
Copy link
Contributor

11happy commented Jan 28, 2024

so I removed this additional condition *Arg->IgnoreParenImpCasts() and ran tests , It broke 92 tests.

********************
********************
Failed Tests (92):
  Clang :: Analysis/osobjectcstylecastchecker_test.cpp
  Clang Tools :: clang-tidy/checkers/abseil/redundant-strcat-calls.cpp
  Clang Tools :: clang-tidy/checkers/abseil/string-find-startswith.cpp
  Clang Tools :: clang-tidy/checkers/bugprone/dangling-handle.cpp
  Clang Tools :: clang-tidy/checkers/bugprone/signal-handler-minimal.c
  Clang Tools :: clang-tidy/checkers/bugprone/signal-handler-posix.c
  Clang Tools :: clang-tidy/checkers/bugprone/signal-handler.c
  Clang Tools :: clang-tidy/checkers/bugprone/signal-handler.cpp
  Clang Tools :: clang-tidy/checkers/bugprone/signed-char-misuse.cpp
  Clang Tools :: clang-tidy/checkers/bugprone/string-integer-assignment.cpp
  Clang Tools :: clang-tidy/checkers/bugprone/undefined-memory-manipulation.cpp
  Clang Tools :: clang-tidy/checkers/bugprone/use-after-move.cpp
  Clang Tools :: clang-tidy/checkers/cert/env33-c.c
  Clang Tools :: clang-tidy/checkers/cert/oop57-cpp.cpp
  Clang Tools :: clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index-gslheader.cpp
  Clang Tools :: clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index.cpp
  Clang Tools :: clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp
  Clang Tools :: clang-tidy/checkers/cppcoreguidelines/slicing.cpp
  Clang Tools :: clang-tidy/checkers/llvm/prefer-isa-or-dyn-cast-in-conditionals.cpp
  Clang Tools :: clang-tidy/checkers/modernize/make-shared.cpp
  Clang Tools :: clang-tidy/checkers/modernize/make-unique-default-init.cpp
  Clang Tools :: clang-tidy/checkers/modernize/make-unique.cpp
  Clang Tools :: clang-tidy/checkers/modernize/use-equals-default-copy.cpp
  Clang Tools :: clang-tidy/checkers/performance/type-promotion-in-math-fn.cpp
  Clang Tools :: clang-tidy/checkers/performance/unnecessary-copy-initialization.cpp
  Clang Tools :: clang-tidy/checkers/readability/redundant-string-cstr.cpp
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/0
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/1
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/10
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/11
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/12
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/13
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/2
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/3
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/4
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/5
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/6
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/7
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/8
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/AllOf/9
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/10
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/11
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/12
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/13
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/4
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/5
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/6
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/7
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/8
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/HasArgument_CXXConstructorDecl/9
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/0
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/1
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/10
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/11
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/12
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/13
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/2
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/3
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/4
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/5
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/6
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/7
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/8
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/ASTMatchersTests/ASTMatchersTest/IsInteger_MatchesIntegers/9
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/GtestAssertTest/ShouldMatchAssert
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/GtestExpectCallTest/CallShouldMatchExpectCallWithParams1
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/GtestExpectCallTest/CallShouldMatchExpectCallWithParams2
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/GtestExpectTest/ShouldMatchExpect
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/GtestOnCallTest/CallShouldMatchOnCallWithParams1
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/GtestOnCallTest/CallShouldMatchOnCallWithParams2
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/Matcher/Argument
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/Matcher/IgnoresElidableConstructors
  Clang-Unit :: ASTMatchers/./ASTMatchersTests/Traversal/traverseUnlessSpelledInSource
  Clang-Unit :: Analysis/./ClangAnalysisTests/ExprMutationAnalyzerTest/UniquePtr
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonIntegers/absl
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonIntegers/base
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonIntegers/std
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonPointerToOptional/absl
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonPointerToOptional/base
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonPointerToOptional/std
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonPointers/absl
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonPointers/base
  Clang-Unit :: Analysis/FlowSensitive/./ClangAnalysisFlowSensitiveTests/UncheckedOptionalUseTestInst/UncheckedOptionalAccessTest/ValueOrComparisonPointers/std
  Clang-Unit :: Tooling/./ToolingTests/StencilTest/CatOfInvalidRangeFails
  Clang-Unit :: Tooling/./ToolingTests/TransformerTest/FunctionMacro
  Clang-Unit :: Tooling/./ToolingTests/TransformerTest/IdentityMacro
  Clang-Unit :: Tooling/./ToolingTests/TransformerTest/MacroArg
  Clang-Unit :: Tooling/./ToolingTests/TransformerTest/MacroArgInMacroDef
  Clang-Unit :: Tooling/./ToolingTests/TransformerTest/OrderedRuleUnrelated
  Clang-Unit :: Tooling/./ToolingTests/TransformerTest/StrlenSize
  Extra Tools Unit Tests :: clang-tidy/./ClangTidyTests/ConstReferenceDeclRefExprsTest/RefVar
  Extra Tools Unit Tests :: clang-tidy/./ClangTidyTests/ConstReferenceDeclRefExprsTest/ValueVar


Testing Time: 645.98s

Total Discovered Tests: 96385
  Skipped          :   333 (0.35%)
  Unsupported      : 30803 (31.96%)
  Passed           : 65077 (67.52%)
  Expectedly Failed:    80 (0.08%)
  Failed           :    92 (0.10%)

@vinayakdsci
Copy link
Contributor

Hello!
If I understand correctly, the task of fixing this issue would require simply the removal of the IgnoreParenImpCasts() from the hasArgument matcher, to make its behavior consistent with hasAnyArgument in this case and then fixing the tests that break consequently?

@AaronBallman
Copy link
Collaborator

Hello! If I understand correctly, the task of fixing this issue would require simply the removal of the IgnoreParenImpCasts() from the hasArgument matcher, to make its behavior consistent with hasAnyArgument in this case and then fixing the tests that break consequently?

That's correct!

@PiotrZSL
Copy link
Member

PiotrZSL commented Mar 4, 2024

Most probably better will be to change all current usages of hasAnyArgument(x) into hasAnyArgument(ignoringParenImpCasts(x))

@komalverma04
Copy link
Contributor

@AaronBallman I would like to take up this issue, please assign it to me.

@komalverma04
Copy link
Contributor

komalverma04 commented Mar 30, 2024

Hi @AaronBallman, I have run LLVM regression tests. And ninja check-clang command is running.Please help me with which tests to run.

@AaronBallman
Copy link
Collaborator

Hi @AaronBallman, I have run LLVM regression tests. And ninja check-clang command is running.Please help me with which tests to run.

ninja check-clang will run all of Clang's tests automatically, but you may also want to run ninja check-clang-tools as well because of how much AST matchers are used by clang-tidy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang-query confirmed Verified by a second party good first issue https://github.com/llvm/llvm-project/contribute
Projects
None yet