This is an archive of the discontinued LLVM Phabricator instance.

PR10405 Missing actual type (aka) in error message when using decltype as a template parameter
ClosedPublic

Authored by nikola on May 1 2014, 7:05 PM.

Details

Reviewers
rsmith
Summary

Desugar TemplateSpecializationType if any of the template arguments is a decltype.

'aka Foo<int>' is much better than 'Foo<decltype(arbitrary expression of type int)>' :)

Diff Detail

Event Timeline

nikola updated this revision to Diff 9028.May 1 2014, 7:05 PM
nikola retitled this revision from to PR10405 Missing actual type (aka) in error message when using decltype as a template parameter.
nikola updated this object.
nikola edited the test plan for this revision. (Show Details)
nikola added a reviewer: rsmith.
rsmith edited edge metadata.May 5 2014, 12:15 AM

This seems like a very special case; I wonder if there's some more general rule we should be using here. (Perhaps we should provide an 'aka' if there's a decltype anywhere in the type?) In any case, the same rule should also apply to GNU __typeof.

nikola added a comment.May 5 2014, 3:48 AM

What cases would we need to handle to make this more generic? I'm thinking FunctionType (return type and parameters) and Template specialization (but at arbitrary nesting level, vector<vector<decltype(something)>>). Have I missed any (plain arrays), and more importantly is there a way to get this info at the moment?

I think the best approach for a template specialization type would probably be to walk the explicitly-specified template arguments, and desugar each one as if it were a top-level type. If you desugar any, rebuild the template specialization type with the desugared type. Doing the same thing for the parameter and return types of function types might also make some sense.

nikola updated this revision to Diff 9097.May 5 2014, 11:25 PM
nikola edited edge metadata.

This should handle templates in a generic way for both decltype and __typeof.

nikola planned changes to this revision.EditedMay 25 2014, 8:39 PM

In what situation would FunctionType show up? In this case x is a PointerType which is not sugared.

int (*x)();
int t = x;

nikola added a subscriber: Unknown Object (MLST).May 25 2014, 8:40 PM

Here's one way to get a diagnostic with a FunctionType in it:

void (&f)(decltype(1+1)) = 0;

This gives:

<stdin>:1:8: error: non-const lvalue reference to type 'void (decltype(1 + 1))' cannot bind to a temporary of type 'int'

lib/AST/ASTDiagnostic.cpp
68–69

Better would be something like "Desugar template specializations if any template argument should be desugared."

70–81

It'd be better here to rebuild a TemplateSpecializationType that has the desugared template arguments in it.

72

Please don't use a TemplateSpecializationType as a container like this; it's not notionally a container of template arguments. Instead, add an arguments member function to TemplateSpecializationType to return the arguments list.

73

Please use 2-space indent, not 4.

nikola requested a review of this revision.May 29 2014, 8:25 PM
nikola added inline comments.
lib/AST/ASTDiagnostic.cpp
72

The class already has getArgs, getNumArgs and getArg methods. But why does it have begin and end if not to be used as a container?

nikola added inline comments.Jun 30 2014, 11:07 PM
lib/AST/ASTDiagnostic.cpp
70–81

What exactly do you mean by rebuild?

rsmith added inline comments.Jul 8 2014, 10:52 AM
lib/AST/ASTDiagnostic.cpp
70–81

I mean, ask the ASTContext to create a new TemplateSpecializationType with the desugared template arguments.

nikola added inline comments.Jul 14 2014, 6:36 PM
lib/AST/ASTDiagnostic.cpp
70–81

I thought it'd be obvious why I was doing this after I did it but I guess I should have asked. At first I though this was an optimization, create this QualType now as it will certainly be created later on. But I've noticed that getting the canonical type from sugared type returns a different type object with same 'spelling'. I know that we're supposed to have only one QualType per type and I'm lost... Is this what you had in mind, and more importantly why?

if (const TemplateSpecializationType *TST =
        dyn_cast<TemplateSpecializationType>(Ty)) {
  SmallVector<TemplateArgument, 4> Args;
  for (TemplateSpecializationType::iterator I = TST->args_begin(),
                                            E = TST->args_end();
       I != E; ++I) {
    if (I->getKind() == TemplateArgument::Type)
      Args.push_back(Desugar(Context, I->getAsType(), ShouldAKA));
    else
      Args.push_back(*I);
  }

  if (ShouldAKA || TST->isTypeAlias()) {
    QT = Context.getTemplateSpecializationType(
        TST->getTemplateName(), Args.data(), Args.size(), QT);
    break;
  }
}
rsmith added inline comments.Jul 16 2014, 4:37 PM
lib/AST/ASTDiagnostic.cpp
70–81

Yes, that's approximately what I had in mind. This way, we should perform an appropriate amount of desugaring on template arguments, and not just flatten them straight to their canonical types.

Comments on that code:

  • ShouldAKA might have been set by something already; track your own variable to determine if you desugared any arguments
  • It would be useful to also desugar non-type template arguments; maybe pick up the canonical TST's template argument if the non-type template argument is in Expression form?
nikola updated this revision to Diff 27568.Jun 12 2015, 3:08 AM

It's been some time since we looked at this.

I'm having issues addressing your last comment, non type template parameters. What's the idea here, to turn A<1+2> into A<int>? While tinkering with this I managed to produce desugar A<1+2> as A<3> by accident so I'm not really sure what you meant.

I was surprised to see that both A<1> and A<1+2> have a TemplateArgument with Expression kind. Having 'aka A<int>' for each A<1> seems too spammy but I couldn't figure out how to differentiate them.

rsmith accepted this revision.Jul 13 2015, 7:33 PM
rsmith edited edge metadata.

Looks great, thanks!

This revision is now accepted and ready to land.Jul 13 2015, 7:33 PM
nikola closed this revision.Jul 15 2015, 6:07 PM

Committed in r242371 with minor changes to preserve nullability attribute.