tomasz-kaminski-sonarsource wrote: Looking at the examples for the static operator at ([live example](https://godbolt.org/z/GhhT5ohh7)): ```c++ struct S { int pad; static void operator()(int x, int y) { // clang_analyzer_dump(x); // clang_analyzer_dump(y); } };
void calls() { S s{10}; void (*fptr)(int, int) = &S::operator(); s(1, 2); // A S::operator()(1, 2); // B fptr(1, 2); // C } ``` You can experiment with the results of the dumps to check current behavior - you need to add `debug.ExprInspection` matcher to see the output. The calls `B` and `C` are represented as the `CallExpr` with 2 arguments, and in static analysis, they are mapped to `SimpleFunctionCall` event. This is no different from handling of any other static member function, that we have currently. However, in the case of `A` the AST is different, as we have `CXXOperatorCallExpr` with 3 arguments being included (the first node is called function). The additional argument is the object argument, which is not later passed to function because it is `static`. ```` CXXOperatorCallExpr <line:13:5, col:11> 'void' '()' |-ImplicitCastExpr <col:6, col:11> 'void (*)(int, int)' <FunctionToPointerDecay> | `-DeclRefExpr <col:6, col:11> 'void (int, int)' lvalue CXXMethod 0xc7ecd78 'operator()' 'void (int, int)' |-DeclRefExpr <col:5> 'S' lvalue Var 0xc7ed028 's' 'S' |-IntegerLiteral <col:7> 'int' 1 `-IntegerLiteral <col:10> 'int' 2 ```` So in this case we also need an adjustment when mapping from arguments to parameters. However, we cannot use `CXXMemberOperatorCall` as we are not calling an implicit object function, and we do not have `this` argument. I think the best way to handle it would be to introduce a new kind of event `CXXStaticOperatorCall`. This event should be based on `SimpleFunctionCall` (I would start it as a copy of it), with some modification derived from `CXXMemberOperatorCall`: * constructor from `CXXOperatorCallExpr` * `getOriginExpr` and `getOverloadedOperator` as we will always use it for `CXXOperatorCallExpr` * `getNumArgs`, `getArgExpr`, `getAdjustedParameterIndex`, and `getASTArgumentIndex` to skip object parameters. [ Note: We do not copy any function related to `this` object, as there is not any. ] Then we need to add a new `CE_CXXStaticOperator` kind, it should be after `CE_Function` and before `CE_CXXMember` as this is not an instance call. ```c++ enum CallEventKind { CE_Function, CE_CXXStaticOperator, CE_CXXMember, CE_CXXMemberOperator, CE_CXXDestructor, CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember, CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor, .... }; ``` Finally, we can change `getSimpleCall` to check for static operators: ``` if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) { const FunctionDecl *DirectCallee = OpCE->getDirectCallee(); if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) { if (MD->isInstance() return create<CXXMemberOperatorCall>(OpCE, State, LCtx, ElemRef); if (MD->isStatic()) return create<CXXStaticOperatorCall>(OpCE, State, LCtx, ElemRef); } } ``` Hope this helps. However, please open such changes in a separate PR. https://github.com/llvm/llvm-project/pull/83585 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits