This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Use resolveTypeToRecordDecl() to resolve the type of a base specifier during heuristic resolution
ClosedPublic

Authored by nridge on Jun 19 2023, 12:10 AM.

Details

Summary

The code for resolving the type of a base specifier was inside
CXXRecordDecl::lookupDependentName(), so this patch reimplements
lookupDependentName() in HeuristicResolver.

Fixes https://github.com/clangd/clangd/issues/1657

Diff Detail

Event Timeline

nridge created this revision.Jun 19 2023, 12:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 19 2023, 12:10 AM
nridge requested review of this revision.Jun 19 2023, 12:10 AM

As this patch involves copying a bit of code from CXXRecordDecl::lookupDepenentName() to HeuristicResolver, I wanted to mention a couple of alternatives I considered:

  1. Copy things in the other direction, i.e. implement some of the necessary parts of resolveTypeToRecordDecl() in the helpers of lookupDependentName() instead. I decided against this because HeuristicResolver is an area of the code that's actively being improved; instead of having to make multiple updates to lookupDependentName() over time, it seems cleaner to just break HeuristicResolver's dependency on that function.
  2. Wait to make this change until after HeuristicResolver has been upstreamed and unified with lookupDependentName(). I do plan to work on this upstreaming, but as the process will involve several steps (e.g. writing new tests, getting approval from relevant upstream maintainers), I would prefer not to block this change on the resolution of that process.

As this patch involves copying a bit of code from CXXRecordDecl::lookupDepenentName() to HeuristicResolver, I wanted to mention a couple of alternatives I considered:

  1. Copy things in the other direction, i.e. implement some of the necessary parts of resolveTypeToRecordDecl() in the helpers of lookupDependentName() instead. I decided against this because HeuristicResolver is an area of the code that's actively being improved; instead of having to make multiple updates to lookupDependentName() over time, it seems cleaner to just break HeuristicResolver's dependency on that function.
  2. Wait to make this change until after HeuristicResolver has been upstreamed and unified with lookupDependentName(). I do plan to work on this upstreaming, but as the process will involve several steps (e.g. writing new tests, getting approval from relevant upstream maintainers), I would prefer not to block this change on the resolution of that process.

Thanks for all thoughtful considerations.
It is a bit sad that we duplicate the implementation in the HeuristicResolver, but given that

  • this part of code is not large
  • we need it in the Resolver anyway when upstreaming to clang

I think it is probably OK to do that.

The other question might worth thinking, are these cases critical to fix now? I'm not sure this->find() is a common case (find(); already works today).

The other question might worth thinking, are these cases critical to fix now? I'm not sure this->find() is a common case (find(); already works today).

I may have simplified the test case a bit too much; a more representative case is one where the base class is a template, and the derived class passes its template parameter to the base:

template <typename T>
struct Waldo {
  void find();
};

template <typename T>
using Wally = Waldo<T>;

template <typename T>
struct S : Wally<T> {
  void Foo() { this->find(); }
};

In a case like, the base class is a "dependent base", and the this-> is required (without it the code doesn't compile, because the compiler only attempts the first phase of the name lookup on find, and that gives no results).

In any case, the code was reduced from a bug report affecting a real codebase.

hokein accepted this revision.Jun 20 2023, 6:41 AM

OK, fair enough. Thanks.

This revision is now accepted and ready to land.Jun 20 2023, 6:41 AM