[PATCH] D47623: [clangd] Avoid indexing decls associated with friend decls.

Ilya Biryukov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 1 06:34:05 PDT 2018


ilya-biryukov added a comment.

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;
    }
  };



================
Comment at: clangd/index/SymbolCollector.cpp:293
   assert(CompletionAllocator && CompletionTUInfo);
+  // A declaration created for a friend declaration should not be used as the
+  // canonical declaration in the index.
----------------
ioeric wrote:
> ilya-biryukov wrote:
> > Maybe move this closer to `shouldFilterDecl()`? We have similar filters there.
> > That would also mean we properly add the reference counts for friend declarations that get a normal declaration after their usage later.
> I didn't put this filter there because I think it's a bit more special than those filters in `shouldFilterDecl`. We check the `OrigD` and we could potentially replace `D` with `OrigD`. We could change `shouldFilterDecl` to handle that, but I'm not sure if it's worth it.
> 
> Reference counting for friend declarations is actually a bit tricky as USRs of the generated declarations might be ambiguous.
> 
>  Consider the following exmaple:
> ```
> namespace a {                
> class A {};                  
> namespace b { class B { friend class A; };  }  // b                          
> } // a                            
> ```
> 
> I would expect the generated friend decl to be `a::A`, but it's actually `a::b::A`! So getting USR right is a bit tricky, and I think it's probably ok to ignore references in friend decls.
> 
> For reference, `[namespace.memdef]p3`:
> "If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
> Reference counting for friend declarations is actually a bit tricky as USRs of the generated declarations might be ambiguous.
This seems like an obvious bug in the USRs that we should fix. WDYT?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D47623





More information about the cfe-commits mailing list