tom-anders marked 12 inline comments as done.
tom-anders added inline comments.


================
Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:314
 //   (these tend to be vague, like Type or Unknown)
+// - Resolved tokens (i.e. without the "dependent-name" modifier) with kind
+//   "Unknown" are less reliable than resolved tokens with other kinds
----------------
nridge wrote:
> sammccall wrote:
> > nridge wrote:
> > > We should consider the case where a dependent name is passed by non-const 
> > > reference, for example:
> > > 
> > > ```
> > > void increment_counter(int&);
> > > 
> > > template <typename T>
> > > void bar() {
> > >    increment_counter(T::static_counter);
> > > }
> > > ```
> > > 
> > > This case does not work yet with the current patch (the dependent name is 
> > > a `DependentScopeDeclRefExpr` rather than a `DeclRefExpr`), but we'll 
> > > want to make it work in the future.
> > > 
> > > With the conflict resolution logic in this patch, the `Unknown` token 
> > > kind from `highlightPassedByNonConstReference()` will be chosen over the 
> > > dependent token kind.
> > > 
> > > As it happens, the dependent token kind for expressions is also `Unknown` 
> > > so it doesn't matter, but perhaps we shouldn't be relying on this. 
> > > Perhaps the following would make more sense:
> > > 
> > > 1. a token with `Unknown` as the kind has the lowest priority
> > > 2. then a token with the `DependentName` modifier (next lowest)
> > > 3. then everything else?
> > The conflict-resolution idea is subtle (and IME hard to debug). I'm wary of 
> > overloading it by deliberately introducing "conflicts" that should actually 
> > be merged. Did you consider the idea of tracking extra modifiers separately 
> > and merging them in at the end?
> > 
> > ---
> > 
> > BTW: we're stretching the meaning of `Unknown` here. There are two subtly 
> > different concepts:
> >  - clangd happens not to have determined the kind of this token, e.g. 
> > because we missed a case (uses in this patch)
> >  - clangd has determined that per C++ rules the kind of token is ambiguous 
> > (uses prior to this patch)
> > Call me weird, but I have "Unknown" highlighted in bright orange in my 
> > editor, because I want to know about the second case :-)
> I don't have a strong opinion on the options here, just wanted to chime in 
> and say I also highlight `Unknown` prominently for similar reasons :)
I switched to @sammccall's idea of having a map<Range, Modifier>, I agree that 
it feels more natural than the previous version


================
Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:514
+  bool VisitCallExpr(CallExpr *E) {
+    // Highlighting parameters passed by non-const reference does not really
+    // make sence for these
----------------
sammccall wrote:
> CXXOperatorCallExpr seems to make sense to me for the most part:
>  - functor calls are CXXOperatorCallExpr
>  - if `x + y` mutates y, I want to know that
> 
> There are some exceptions though:
>   - the functor object itself is more like the function callee, and to be 
> consistent we shouldn't highlight it
>   - highlighting `x` in `x += y` is weird
>   - `a << b` is a weird ambiguous case ("stream" vs "shift" want different 
> behavior)
> 
> I think these can be handled by choosing a minimum argument index to 
> highlight based on the operator type.
> 
> I think it makes sense to leave operators out of scope for this patch, but 
> IMO should be a "FIXME" rather than a "let's never do this" :-)
Agreed, added a FIXME


================
Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:542
+        // Is this parameter passed by non-const reference?
+        if (T->isLValueReferenceType() && !isConst(T)) {
+          if (auto *Arg = GetArgExprAtIndex(I)) {
----------------
sammccall wrote:
> nridge wrote:
> > I think there are some edge cases where `isConst()` doesn't do what we want.
> > 
> > For example, I think for a parameter of type `const int*&`, it will return 
> > `true` (and thus we will **not** highlight the corresponding argument), 
> > even thus this is actually a non-const reference.
> > 
> > So, we may want to use a dedicated function that specifically handles 
> > reference-related logic only.
> > 
> > (This probably also makes a good test case.)
> Yeah this is the core of this modifier, worth being precise and explicit 
> here. I think we want to match only reference types where the inner type is 
> not top-level const.
> 
> I think we should also conservatively forbid the inner type from being 
> *dependent*. Consider the following function:
> 
> ```
> template <typename X>
> void foo(X& x) {
>   foo(x); // this call
> }
> ```
> 
> Locally, the recursive call looks like "mutable reference to dependent type". 
> But when instantiated, X may be `const int` and is in fact very likely to be 
> deduced that way in practice.
I adjusted the condition accordingly and added a few more test cases (including 
stuff like `const int*&`). 


================
Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:546
+
+            if (isa<DeclRefExpr>(Arg)) {
+              Location = Arg->getBeginLoc();
----------------
sammccall wrote:
> You may want to add an "unwrapping" step so that e.g. ArraySubscriptExpr 
> `a[i]` can be unwrapped to `a` and then possibly highlighted (and its 
> operator-overloaded form).
> 
> Wouldn't suggest doing that in this patch, but you could leave a note if you 
> like.
Added a FIXME.


================
Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:547
+            if (isa<DeclRefExpr>(Arg)) {
+              Location = Arg->getBeginLoc();
+            } else if (auto *M = dyn_cast<MemberExpr>(Arg)) {
----------------
tom-anders wrote:
> sammccall wrote:
> > tom-anders wrote:
> > > sammccall wrote:
> > > > nridge wrote:
> > > > > For a qualified name (e.g. `A::B`), I think this is going to return 
> > > > > the beginning of the qualifier, whereas we only want to highlight the 
> > > > > last name (otherwise there won't be a matching token from the first 
> > > > > pass).
> > > > > 
> > > > > So I think we want `getLocation()` instead.
> > > > > 
> > > > > (Also makes a good test case.)
> > > > And getLocation() will do the right thing for DeclRefExpr, MemberExpr, 
> > > > and others, so this can just be `isa<DeclRefExpr, MemberExpr>` with no 
> > > > need for dyn_cast.
> > > I'm not sure which getLocation() you're talking about here. There's 
> > > DeclRefExpr::getLocation(), but neither Expr::getLocation() nor 
> > > MemberExpr::getLocation(). Am I missing something?
> > No, I think I'm just going mad (I was thinking of Decl::getLocation I 
> > guess).
> > Never mind and sorry!
> np :D 
Switched to `getLocation()` and added a test case.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D108320

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to