1717#include " clang/AST/DynamicRecursiveASTVisitor.h"
1818#include " clang/AST/Expr.h"
1919#include " clang/AST/ExprCXX.h"
20+ #include " clang/AST/Mangle.h"
21+ #include " clang/AST/RecursiveASTVisitor.h"
22+ #include " clang/AST/TemplateBase.h"
2023#include " clang/AST/TemplateName.h"
24+ #include " clang/AST/Type.h"
25+ #include " clang/AST/TypeOrdering.h"
2126#include " clang/AST/TypeVisitor.h"
2227#include " clang/Basic/Builtins.h"
2328#include " clang/Basic/DiagnosticSema.h"
3641#include " clang/Sema/SemaInternal.h"
3742#include " clang/Sema/Template.h"
3843#include " clang/Sema/TemplateDeduction.h"
44+ #include " llvm/ADT/ArrayRef.h"
45+ #include " llvm/ADT/BitVector.h"
46+ #include " llvm/ADT/DenseSet.h"
47+ #include " llvm/ADT/STLExtras.h"
3948#include " llvm/ADT/SmallBitVector.h"
49+ #include " llvm/ADT/SmallString.h"
50+ #include " llvm/ADT/SmallVector.h"
4051#include " llvm/ADT/StringExtras.h"
4152#include " llvm/Support/SaveAndRestore.h"
53+ #include " llvm/Support/raw_ostream.h"
4254
4355#include < optional>
4456using namespace clang ;
@@ -3320,6 +3332,78 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
33203332 }
33213333 return HasNoTypeMember;
33223334 }
3335+ case BTK__builtin_dedup_types: {
3336+ assert (Converted.size () == 1 && " __builtin_dedup_types should be given "
3337+ " a parameter pack" );
3338+ TemplateArgument Ts = Converted[0 ];
3339+ // Delay the computation until we can compute the final result. We choose
3340+ // not to remove the duplicates upfront before substitution to keep the code
3341+ // simple.
3342+ if (Ts.isDependent ())
3343+ return Context.getCanonicalTemplateSpecializationType (TemplateName (BTD),
3344+ Converted);
3345+ assert (Ts.getKind () == clang::TemplateArgument::Pack);
3346+ llvm::SmallVector<TemplateArgument> OutArgs;
3347+ llvm::SmallDenseSet<QualType> Seen;
3348+ // Synthesize a new template argument list, removing duplicates.
3349+ for (auto T : Ts.getPackAsArray ()) {
3350+ assert (T.getKind () == clang::TemplateArgument::Type);
3351+ if (!Seen.insert (T.getAsType ().getCanonicalType ()).second )
3352+ continue ;
3353+ OutArgs.push_back (T);
3354+ }
3355+ // Return __builtin_expand_types, it will handle the final expansion.
3356+ return Context.getCanonicalTemplateSpecializationType (
3357+ TemplateName (Context.get__builtin_expand_typesDecl ()), OutArgs);
3358+ }
3359+ case BTK__builtin_sort_types: {
3360+ assert (Converted.size () == 1 );
3361+ assert (Converted[0 ].getKind () == TemplateArgument::Pack);
3362+ // Delay if we have any dependencies, the mangled names may change after
3363+ // subsistution or may not be well-defined for dependent types.
3364+ if (Converted[0 ].isDependent ())
3365+ return Context.getCanonicalTemplateSpecializationType (TemplateName (BTD),
3366+ Converted);
3367+
3368+ auto InputArgs = Converted[0 ].getPackAsArray ();
3369+ std::unique_ptr<MangleContext> Mangler (
3370+ SemaRef.getASTContext ().createMangleContext ());
3371+
3372+ // Prepare our sort keys, i.e. the mangled names.
3373+ llvm::SmallVector<std::string> MangledNames (InputArgs.size ());
3374+ for (unsigned I = 0 ; I < InputArgs.size (); ++I) {
3375+ llvm::raw_string_ostream OS (MangledNames[I]);
3376+ Mangler->mangleCanonicalTypeName (
3377+ InputArgs[I].getAsType ().getCanonicalType (), OS);
3378+ }
3379+
3380+ // Sort array of indices into the InputArgs/MangledNames.
3381+ llvm::SmallVector<unsigned > Indexes (InputArgs.size ());
3382+ for (unsigned I = 0 ; I < InputArgs.size (); ++I) {
3383+ Indexes[I] = I;
3384+ }
3385+ llvm::stable_sort (Indexes, [&](unsigned L, unsigned R) {
3386+ return MangledNames[L] < MangledNames[R];
3387+ });
3388+
3389+ llvm::SmallVector<TemplateArgument> SortedArguments;
3390+ SortedArguments.reserve (InputArgs.size ());
3391+ for (unsigned I : Indexes)
3392+ SortedArguments.push_back (InputArgs[I]);
3393+
3394+ // Use __builtin_expand_types to indicate we now have the final results.
3395+ return Context.getCanonicalTemplateSpecializationType (
3396+ TemplateName (Context.get__builtin_expand_typesDecl ()), SortedArguments);
3397+ }
3398+ case BTK__builtin_expand_types: {
3399+ assert (Converted.size () == 1 );
3400+ assert (Converted[0 ].getKind () == TemplateArgument::Pack);
3401+ auto InputArgs = Converted[0 ].getPackAsArray ();
3402+ // Just return he inputs as is, the code processing template argument lists
3403+ // recognizes our builtin and does the actual expansion.
3404+ return Context.getCanonicalTemplateSpecializationType (TemplateName (BTD),
3405+ InputArgs);
3406+ }
33233407 }
33243408 llvm_unreachable (" unexpected BuiltinTemplateDecl!" );
33253409}
@@ -5501,6 +5585,70 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
55015585 return true ;
55025586}
55035587
5588+ // / If there is a top-level __builtin_expand_types, it gets expanded and
5589+ // / replaced with its underlying arguments.
5590+ static void
5591+ TryExpandBuiltinTemplateArgumentWrapper (Sema &S,
5592+ TemplateArgumentListInfo &ArgList) {
5593+ auto &Context = S.getASTContext ();
5594+ llvm::ArrayRef<TemplateArgumentLoc> Args = ArgList.arguments ();
5595+
5596+ // These builtins are rare, so defer doing anything until we actually see one.
5597+ llvm::SmallVector<unsigned > ExpandableIndices;
5598+ for (unsigned I = 0 ; I < Args.size (); ++I) {
5599+ auto A = Args[I].getArgument ();
5600+ if (A.getKind () != TemplateArgument::Type)
5601+ continue ;
5602+ auto *TST = A.getAsType ()
5603+ .getDesugaredType (Context)
5604+ ->getAs <TemplateSpecializationType>();
5605+ if (!TST)
5606+ continue ;
5607+ auto TName = TST->getTemplateName ();
5608+ if (TName.getKind () == TemplateName::DeducedTemplate)
5609+ continue ;
5610+ auto *T = dyn_cast_or_null<BuiltinTemplateDecl>(TName.getAsTemplateDecl ());
5611+ if (!T || T->getBuiltinTemplateKind () != clang::BTK__builtin_expand_types)
5612+ continue ;
5613+ ExpandableIndices.push_back (I);
5614+ }
5615+ if (ExpandableIndices.empty ())
5616+ return ;
5617+
5618+ // We know that some expansion needs to take place, so prepare to do it.
5619+ TemplateArgumentListInfo ExpandedArgList;
5620+ unsigned NextUnprocessedArg = 0 ;
5621+ auto CopyUpTo = [&](unsigned J) {
5622+ for (; NextUnprocessedArg < J; ++NextUnprocessedArg) {
5623+ ExpandedArgList.addArgument (ArgList[NextUnprocessedArg]);
5624+ }
5625+ };
5626+
5627+ // Do the actual expansion by looping over the indices we identified before.
5628+ for (unsigned NextExpandable : ExpandableIndices) {
5629+ CopyUpTo (NextExpandable);
5630+ // FIXME: attemp to carry around source location information.
5631+ auto ToExpand = Args[NextExpandable]
5632+ .getArgument ()
5633+ .getAsType ()
5634+ .getDesugaredType (Context)
5635+ ->getAs <TemplateSpecializationType>()
5636+ ->template_arguments ();
5637+ for (TemplateArgument A : ToExpand) {
5638+ assert (A.getKind () == TemplateArgument::Type);
5639+ ExpandedArgList.addArgument (TemplateArgumentLoc (
5640+ A, Context.getTrivialTypeSourceInfo (A.getAsType ())));
5641+ }
5642+ NextUnprocessedArg = NextExpandable + 1 ;
5643+ }
5644+
5645+ // Carry over any leftovers.
5646+ CopyUpTo (ArgList.size ());
5647+ assert (NextUnprocessedArg == ArgList.size ());
5648+
5649+ ArgList = std::move (ExpandedArgList);
5650+ }
5651+
55045652// / Check that the given template argument list is well-formed
55055653// / for specializing the given template.
55065654bool Sema::CheckTemplateArgumentList (
@@ -5517,6 +5665,10 @@ bool Sema::CheckTemplateArgumentList(
55175665 // template.
55185666 TemplateArgumentListInfo NewArgs = TemplateArgs;
55195667
5668+ // Process any immediate pack expansions from builtin templates.
5669+ // E.g. from __builtin_sort_types.
5670+ TryExpandBuiltinTemplateArgumentWrapper (*this , NewArgs);
5671+
55205672 TemplateParameterList *Params = GetTemplateParameterList (Template);
55215673
55225674 SourceLocation RAngleLoc = NewArgs.getRAngleLoc ();
0 commit comments