17
17
#include " clang/AST/DynamicRecursiveASTVisitor.h"
18
18
#include " clang/AST/Expr.h"
19
19
#include " clang/AST/ExprCXX.h"
20
+ #include " clang/AST/Mangle.h"
21
+ #include " clang/AST/RecursiveASTVisitor.h"
22
+ #include " clang/AST/TemplateBase.h"
20
23
#include " clang/AST/TemplateName.h"
24
+ #include " clang/AST/Type.h"
25
+ #include " clang/AST/TypeOrdering.h"
21
26
#include " clang/AST/TypeVisitor.h"
22
27
#include " clang/Basic/Builtins.h"
23
28
#include " clang/Basic/DiagnosticSema.h"
36
41
#include " clang/Sema/SemaInternal.h"
37
42
#include " clang/Sema/Template.h"
38
43
#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"
39
48
#include " llvm/ADT/SmallBitVector.h"
49
+ #include " llvm/ADT/SmallString.h"
50
+ #include " llvm/ADT/SmallVector.h"
40
51
#include " llvm/ADT/StringExtras.h"
41
52
#include " llvm/Support/SaveAndRestore.h"
53
+ #include " llvm/Support/raw_ostream.h"
42
54
43
55
#include < optional>
44
56
using namespace clang ;
@@ -3320,6 +3332,78 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
3320
3332
}
3321
3333
return HasNoTypeMember;
3322
3334
}
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
+ }
3323
3407
}
3324
3408
llvm_unreachable (" unexpected BuiltinTemplateDecl!" );
3325
3409
}
@@ -5501,6 +5585,70 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
5501
5585
return true ;
5502
5586
}
5503
5587
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
+
5504
5652
// / Check that the given template argument list is well-formed
5505
5653
// / for specializing the given template.
5506
5654
bool Sema::CheckTemplateArgumentList (
@@ -5517,6 +5665,10 @@ bool Sema::CheckTemplateArgumentList(
5517
5665
// template.
5518
5666
TemplateArgumentListInfo NewArgs = TemplateArgs;
5519
5667
5668
+ // Process any immediate pack expansions from builtin templates.
5669
+ // E.g. from __builtin_sort_types.
5670
+ TryExpandBuiltinTemplateArgumentWrapper (*this , NewArgs);
5671
+
5520
5672
TemplateParameterList *Params = GetTemplateParameterList (Template);
5521
5673
5522
5674
SourceLocation RAngleLoc = NewArgs.getRAngleLoc ();
0 commit comments