Page MenuHomePhabricator

[clangd] Implement hover for "auto" and "decltype"

Authored by malaperle on Jun 13 2018, 8:33 PM.



This allows hovering on keywords that refer to deduced types.
This should cover most useful cases. Not covered:

  • auto template parameters: Since this can be instantiated with many types,

it would not be practical to show the types.

  • Structured binding: This could be done later to show multiple deduced types

in the hover.

  • auto:: (part of concepts): Outside the scope of this patch.

Signed-off-by: Marc-Andre Laperle <>

Diff Detail


Event Timeline

malaperle created this revision.Jun 13 2018, 8:33 PM
sammccall accepted this revision.Jun 27 2018, 12:41 AM

This is so great, thank you!

544 ↗(On Diff #152958)

maybe a bit more context: "we use this to display the actual type when hovering over an auto keyword or decltype() expression"

546 ↗(On Diff #152958)

nit: SourceLocation is 32 bits, just copy it?
(Reference seems fine here but less obvious than it could be)

559 ↗(On Diff #152958)

out of curiosity, why not implement VisitTypeLoc and handle all the cases where it turns out to be auto etc?
Even for auto& I'd expect the inner auto to have a TypeLoc you could visit, saving the trouble of unwrapping.

(I'm probably wrong about all this, I don't know the AST well. But I'd like to learn!)

640 ↗(On Diff #152958)

This is a really nice standalone piece of logic.
It might be slightly cleaner to put it in AST.h with fine-grained unit-tests there, and just smoke test it here. That way this file is more focused on *what* the features do, and the lower layer has details about how they work.
(And if we find another use for this, like a "replace with deduced type" refactoring, we could easily reuse it).

That said, the current stuff in this file doesn't exhibit that layering/separation today. Happy if you prefer to land it here, and I/someone may do such a refactoring in the future.

656 ↗(On Diff #152958)

This will end up deserializing the whole preamble I think, which is slow.
The fix is just to traverse from each of the top-level *non-preamble* decls instead, i.e. AST.getLocalTopLevelDecls().

(we've fixed this bug many times so far, it would be nice if there's a systematic way to fix/catch this but I can't think of one)

47 ↗(On Diff #152958)

headerSymbols() and index() also depend on these flags - can you make these extra args a member instead? (can be public, just like Code)

This revision is now accepted and ready to land.Jun 27 2018, 12:41 AM
malaperle marked 4 inline comments as done.Jun 27 2018, 12:27 PM
malaperle added inline comments.
559 ↗(On Diff #152958)

From what I saw, there are actually two different AutoType* for each textual "auto". The AutoType* containing the deduced type does not get visited via a typeloc. It's not entirely clear to me why since I don't know the AST well either. I was thinking maybe the first is created when the type is not deduced yet and later on, then the rest of the function or expression is parsed, a second one with the actual type deduced is created. If I look at the code paths where they are created, it seems like this is roughly what's happening. The first one is created when the declarator is parsed (no deduced type yet) and the second is created when the expression of the initializer (or return statement) is evaluated and the type is then deduced. The visitor only visits the first one's typeloc. I don't think I'm knowledgeable enough to say whether or not that's a bug but it seems on purpose that it is modelled this way. Although it would be much nicer to only have to visit typelocs...

640 ↗(On Diff #152958)

Good idea! The refactoring would be a neat feature too. I think I'd prefer to leave this refactoring for a bit later since this patch looks like it's close to ready to go.

Address comments.

sammccall accepted this revision.Jun 28 2018, 1:12 AM
sammccall added a subscriber: klimek.

All sounds good to me.

559 ↗(On Diff #152958)

The AutoType* containing the deduced type does not get visited via a typeloc

Ah, OK.
Could you add a high level comment (maybe on the class) saying this is the reason for the implementation? Otherwise as a reader I'll think "this seems unneccesarily complicated" but not understand why.

@klimek Can you shed any light on this?

klimek added inline comments.Jun 28 2018, 1:18 AM
559 ↗(On Diff #152958)

Can't you go from AutoTypeLoc -> AutoType -> getDeducedType()?

malaperle added inline comments.Jun 28 2018, 1:41 PM
559 ↗(On Diff #152958)

The visitor doesn't visit the AutoTypeLoc that has the deduced type. In fact, there are two AutoType* instances. I'm not sure that's is a bug that there are two AutoType*, or if not visiting both AutoTypeLoc is a bug...or neither.

klimek added inline comments.
559 ↗(On Diff #152958)

+Richard Smith:

This is weird. If I just create a minimal example:

int f() {
  auto i = f();
  return i;

I only get the undeduced auto type - Richard, in which cases are auto-typed being deduced? The AST dump doens't give an indication that there was an auto involved at all. Is this the famous syntactic vs. smenatic form problem? Do we have a backlink between the AutoTypeLoc and the deduced type somewhere?

malaperle updated this revision to Diff 153612.Jun 29 2018, 9:38 PM

Add comment about AutoTypeLoc work-around.

klimek accepted this revision.Jul 2 2018, 12:22 AM
klimek added inline comments.
559 ↗(On Diff #152958)

Given that Richard is known to have ~1 month ping times now and then I think it's fine to land this with a FIXME above to figure out how to represent this better in the AST. I'd still say it's a missing feature in the AST :)

malaperle updated this revision to Diff 153737.Jul 2 2018, 9:28 AM

Tweak comment with FIXME.

malaperle added inline comments.Jul 2 2018, 9:28 AM
559 ↗(On Diff #152958)

Thanks! I'm looking forward to simplifying this code when the AST is improved.

This revision was automatically updated to reflect the committed changes.