This is an archive of the discontinued LLVM Phabricator instance.

[clang] Fixes how we represent / emulate builtin templates
ClosedPublic

Authored by mizvekov on Sep 3 2022, 2:10 PM.

Details

Summary

We change the template specialization of builtin templates to
behave like aliases.

Though unlike real alias templates, these might still produce a canonical
TemplateSpecializationType when some important argument is dependent.

For example, we can't do anything about make_integer_seq when the
count is dependent, or a type_pack_element when the index is dependent.

We change type deduction to not try to deduce canonical TSTs of
builtin templates.

We also change those buitin templates to produce substitution sugar,
just like a real instantiation would, making the resulting type correctly
represent the template arguments used to specialize the underlying template.

And make_integer_seq will now produce a TST for the specialization
of it's first argument, which we use as the underlying type of
the builtin alias.

When performing member access on the resulting type, it's now
possible to map from a Subst* node to the template argument
as-written used in a regular fashion, without special casing.

And this fixes a bunch of bugs with relation to these builtin
templates factoring into deduction.

Fixes GH42102 and GH51928.

Depends on D133261

Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>

Diff Detail

Event Timeline

mizvekov created this revision.Sep 3 2022, 2:10 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 3 2022, 2:10 PM
mizvekov requested review of this revision.Sep 3 2022, 2:10 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 3 2022, 2:10 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
mizvekov updated this revision to Diff 457816.Sep 3 2022, 2:11 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 3 2022, 2:11 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript
mizvekov updated this revision to Diff 457817.Sep 3 2022, 2:21 PM

There are some known bugs about how we handle this built-in in the AST- #42102, #51928, #54993. Is it possible that your patch solves them? It would be great if it does, I hit one of them in the wild a while back.

There are some known bugs about how we handle this built-in in the AST- #42102, #51928, #54993. Is it possible that your patch solves them? It would be great if it does, I hit one of them in the wild a while back.

I think not, these look like deduction problems, and what is done in this patch should not affect deduction.

The TemplateSpecializationTypes we are changing in this patch are all sugar, and these should not affect it.

Dependence can create canonical TST, which does affect it, but checkBuiltinTemplateIdType is not even called if there is any dependence.

davrec accepted this revision.Sep 5 2022, 11:41 AM

LGTM aside from a nit

clang/include/clang/AST/DeclTemplate.h
458

Add doc, e.g. "Whether this is a written or built-in type alias template."

And nit: maybe move this above the classof functions, since those and other boilerplate functions are usually the last public members.

erichkeane added inline comments.Sep 6 2022, 6:16 AM
clang/lib/AST/DeclTemplate.cpp
257

This seems strange to me that ONLY this one builtin is what makes a template a 'type alias'. This needs to have a more descriptive name here, IMO.

262

The semicolon after default is bizarre/unnecessary. That said, I'd suggest just making the 'default' case be 'return false'.

clang/lib/Sema/SemaTemplate.cpp
3559–3560

Can you update the comment here ot accurately describe what is going on below?

mizvekov updated this revision to Diff 458541.Sep 7 2022, 12:51 PM
mizvekov retitled this revision from [clang] Represent __make_integer_seq as alias template in the AST to [clang] Fixes how we represent / emulate builtin templates.
mizvekov edited the summary of this revision. (Show Details)
mizvekov marked 3 inline comments as done.
mizvekov added inline comments.Sep 7 2022, 12:52 PM
clang/lib/AST/DeclTemplate.cpp
262

This is just a workaround for some versions of GCC and/or MSVC which warn on control flow reaching the end of the function, even in cases such as a switch which returns in all paths.
Also we prefer to emit a warning on unhandled cases when omitting the default case.

So this is a compact way of avoiding those issues without having to add a llvm_unreachable("control flow should never get here"); at the end.

Have we gotten rid of the old versions of those toolchains which had this problem?

mizvekov added a comment.EditedSep 7 2022, 12:54 PM

There are some known bugs about how we handle this built-in in the AST- #42102, #51928, #54993. Is it possible that your patch solves them? It would be great if it does, I hit one of them in the wild a while back.

@royjacobson I decided to do a complete job here and fix all those issues except #54993. Can you confirm?

I also applied the same idea to type_pack_element as I saw a crash related to that in the wild.

mizvekov updated this revision to Diff 458553.Sep 7 2022, 1:53 PM
mizvekov updated this revision to Diff 458559.Sep 7 2022, 2:23 PM
mizvekov edited the summary of this revision. (Show Details)
mizvekov updated this revision to Diff 458586.Sep 7 2022, 3:50 PM
mizvekov marked an inline comment as done.Sep 7 2022, 3:52 PM
mizvekov added inline comments.
clang/lib/AST/DeclTemplate.cpp
262

Removed as I just confirmed we don't need it.

erichkeane accepted this revision.Sep 7 2022, 6:20 PM

@royjacobson I decided to do a complete job here and fix all those issues except #54993. Can you confirm?

I also applied the same idea to type_pack_element as I saw a crash related to that in the wild.

That's amazing to hear, thanks for looking at it! I haven't had time to check it yet, but could you add the snippets from the bug reports as regression tests?

@royjacobson I decided to do a complete job here and fix all those issues except #54993. Can you confirm?

I also applied the same idea to type_pack_element as I saw a crash related to that in the wild.

That's amazing to hear, thanks for looking at it! I haven't had time to check it yet, but could you add the snippets from the bug reports as regression tests?

The snippets from the bug reports are using libc++ and std::make_integer_sequence directly, which we avoid in these kinds of regression tests, we tend to make very reduced test cases that compile standalone.

But I believe I included reductions that should show we fixed the same problem, unless I missed some specific case.

The snippets from the bug reports are using libc++ and std::make_integer_sequence directly, which we avoid in these kinds of regression tests, we tend to make very reduced test cases that compile standalone.

But I believe I included reductions that should show we fixed the same problem, unless I missed some specific case.

I haven't seen something similar enough to the default template argument case from 42102, so it would be nice to add that one. std::make_integer_sequence is just a type alias template to the builtin, so you can do

template <class A1, A1... A2> struct A {};

// GH42102

template<int S>
using make_index_sequence = __make_integer_seq<A, int, S>;

template <int S, class=make_index_sequence<S>>
struct FooList;
template <int S, int... Idxs>
struct FooList<S, A<int, Idxs...>> { };

template <int S>
void foobar(FooList<S>) { }

void test() { 
  foobar(FooList<5>{});
}

// GH51928

template <typename T, typename Seq>
struct X;

template <typename T>
struct X<T, make_index_sequence<sizeof(T)>> {
};

X<char, make_index_sequence<1>> x;

to get unittests without libc++.

mizvekov updated this revision to Diff 459365.Sep 11 2022, 7:46 AM
mizvekov updated this revision to Diff 460073.Sep 14 2022, 7:03 AM
mizvekov updated this revision to Diff 460590.Sep 15 2022, 6:10 PM
This revision was not accepted when it landed; it landed in state Needs Review.Sep 16 2022, 8:45 AM
This revision was automatically updated to reflect the committed changes.