[PATCH] D119077: clangd SemanticHighlighting: added support for highlighting overloaded operators

Nathan Ridge via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 28 00:11:15 PST 2022


nridge added a comment.

In D119077#3339812 <https://reviews.llvm.org/D119077#3339812>, @iannisdezwart wrote:

> About your comment on the implicit calls to `operator[]` and `operator()`,
> this was also a workaround. Do you have any idea how to get both parentheses from a single `DeclRefExpr`?
> I researched this, but haven't yet found the answer.

Looking at the AST for some example code like this:

  struct S {
    void operator()(int);
  };
  
  int main() {
    S s;
    s(2);
  }

the AST for the line with the implicit call looks like this:

  `-CXXOperatorCallExpr 0x9f9ec0 <line:7:3, col:6> 'void' '()'
    |-ImplicitCastExpr 0x9f9ea8 <col:4, col:6> 'void (*)(int)' <FunctionToPointerDecay>
    | `-DeclRefExpr 0x9f9e58 <col:4, col:6> 'void (int)' lvalue CXXMethod 0x9f9588 'operator()' 'void (int)'
    |-DeclRefExpr 0x9f9e18 <col:3> 'S' lvalue Var 0x9f97c0 's' 'S'
    `-IntegerLiteral 0x9f9e38 <col:5> 'int' 2

Note the `CXXOperatorCallExpr` spand the `s(2)` (columns 3 through 6), and `DeclRefExpr` for the call operator spans the `(2)` (columns 4 through 6).

The current impl uses `DeclRefExpr::getLocation()` to grab the `(`, and `CXXOperatorCallExpr::getOperatorLoc()` to grab the `)`. The latter works because `getOperatorLoc()` is documented <https://searchfox.org/llvm/rev/850bc76a356b050b92851ad5a6a8207da05685cd/clang/include/clang/AST/ExprCXX.h#147> to behave this way:

  /// When \c getOperator()==OO_Call, this is the location of the right
  /// parentheses; when \c getOperator()==OO_Subscript, this is the location
  /// of the right bracket.

I've proposed that we switch to using `DeclRefExpr::getNameInfo().getCXXOperatorNameRange()` as the range to highlight. It now occurs to me that for implicit `( )` and `[ ]`, this is likely to return a range that includes the arguments as well, which we don't want. So, we may need to check implicit vs. explicit, and for implicit highlight the start and end tokens separately. Two potential ways for how to do that:

1. Highlight `DeclRefExpr::getLocation()`. Check if `DeclRefExpr::getEndLoc()` is different, and if so highlight that too.
2. Same as the current patch, continue visiting `CXXOperatorCallExpr`, highlight `CXXOperatorCallExpr::getOperatorLoc()`, and for `(` and `[` also highlight `DeclRefExpr::getLocation()`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119077/new/

https://reviews.llvm.org/D119077



More information about the cfe-commits mailing list