ioeric added a comment.

In https://reviews.llvm.org/D47623#1118951, @ilya-biryukov wrote:

> In https://reviews.llvm.org/D47623#1118810, @sammccall wrote:
>
> > - friend decls that are not definitions should be ignored for indexing 
> > purposes
>
>
> This is not generally true IIUC. A friend declaration can be a reference, a 
> declaration or a definition.
>
>   int foo(int);
>   int bar(int, int);
>   class ExistingFwdCls;
>  
>   class X {
>     friend class ExistingFwdCls; // a reference and a declaration.
>     friend class NewClass; // a new declaration.
>     friend int foo(int); // a reference and a declaration.
>     friend int baz(int, int, int); // a new declaration.
>   };
>  
>   class Y {
>     friend class ::ExistingFwdCls; // qualified => just a reference.
>     friend int ::bar(int a, int b); // qualified => just a reference.
>     friend int foo(int) { // a reference  and a definition
>       return 100;
>     }
>   };
>
>
> Note that friend functions with bodies are probably ok as canonical 
> declaration, as they are often the only declaration, e.g.
>
>   class Foo {
>     friend bool operator < (Foo const& lhs, Foo const&lhs) {
>      return false;
>     }
>   };
>


Sorry for the late response Ilya. I was trying to test these cases. So, with 
the current change, if a real "canonical" declaration comes before the friend 
decl, then the reference will still be recorded (I've added a test case for 
this). Would this address your concern?



================
Comment at: clangd/index/SymbolCollector.cpp:303
+  // canonical declaration in the index.
+  if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
+    D = ASTNode.OrigD;
----------------
sammccall wrote:
> Ah, now I understand - we're picking another to use as canonical. But the 
> exception for definitions should apply here too. And there's nothing special 
> about *OrigD* that makes it a good pick for canonical.
> 
> For determinism, can we instead iterate over the redecls of D and pick the 
> first one that's not a friend or is a definition?
> 
> (I'd pull that check out into a function `shouldSkipDecl` and rename the 
> existing one `shouldSkipSymbol`, but up to you)
> But the exception for definitions should apply here too
I'm not sure why this is needed. Do you have an example?

> And there's nothing special about *OrigD* that makes it a good pick for 
> canonical.
I think `OrigD` is "special" because we have checked that it's not an 
uninteresting friend decl.

> For determinism, can we instead iterate over the redecls of D and pick the 
> first one that's not a friend or is a definition?
This seems to be the most ideal option, although, in practice, it's a bit hard 
to check if each `redecl` is a definition, as we don't have `Roles` for them. 
To make it more deterministic, I added a map from clang's canonical decl to 
clangd's "canonical" decl so that we could be sure that all redecls would have 
the same `D`. WDYT?

>(I'd pull that check out into a function shouldSkipDecl and rename the 
>existing one shouldSkipSymbol, but up to you)
I gave this a try, but it couldn't find a very good abstraction. Happy to chat 
more next week.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D47623



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

Reply via email to