@@ -449,6 +449,13 @@ void ASTPrinter::printEscapedStringLiteral(StringRef str) {
449
449
printTextImpl (escapeBuf.str ());
450
450
}
451
451
452
+ // Returns true if the given declaration is backed by a C++ template
453
+ // specialization.
454
+ static bool isSpecializedCxxDecl (const Decl *D) {
455
+ return D->hasClangNode () &&
456
+ isa<clang::ClassTemplateSpecializationDecl>(D->getClangDecl ());
457
+ }
458
+
452
459
void ASTPrinter::printTypeRef (Type T, const TypeDecl *RefTo, Identifier Name,
453
460
PrintNameContext Context) {
454
461
if (isa<GenericTypeParamDecl>(RefTo)) {
@@ -459,7 +466,7 @@ void ASTPrinter::printTypeRef(Type T, const TypeDecl *RefTo, Identifier Name,
459
466
Context = PrintNameContext::ClassDynamicSelf;
460
467
}
461
468
462
- printName (Name, Context);
469
+ printName (Name, Context, isSpecializedCxxDecl (RefTo) );
463
470
}
464
471
465
472
void ASTPrinter::printModuleRef (ModuleEntity Mod, Identifier Name) {
@@ -558,19 +565,25 @@ ASTPrinter &operator<<(ASTPrinter &printer, tok keyword) {
558
565
}
559
566
560
567
// / Determine whether to escape the given keyword in the given context.
561
- bool swift::escapeIdentifierInContext (Identifier name,
562
- PrintNameContext context ) {
568
+ bool swift::escapeIdentifierInContext (Identifier name, PrintNameContext context,
569
+ bool isSpecializedCxxTemplate ) {
563
570
StringRef keyword = name.str ();
564
571
bool isKeyword = llvm::StringSwitch<bool >(keyword)
565
572
#define KEYWORD (KW ) \
566
573
.Case (#KW, true )
567
574
#include " swift/AST/TokenKinds.def"
568
575
.Default (false );
569
576
577
+ // NB: ClangImporter synthesizes C++ template specializations with Identifiers
578
+ // that contain the full type signature; e.g., a type named literally
579
+ // `X<Y, Z>`. These would normally be interpreted as raw identifiers and
580
+ // escaped with backticks, but we need to avoid that for those specific decls.
581
+
570
582
switch (context) {
571
583
case PrintNameContext::Normal:
572
584
case PrintNameContext::Attribute:
573
- return isKeyword || name.mustAlwaysBeEscaped ();
585
+ return isKeyword ||
586
+ (!isSpecializedCxxTemplate && name.mustAlwaysBeEscaped ());
574
587
case PrintNameContext::Keyword:
575
588
case PrintNameContext::IntroducerKeyword:
576
589
return false ;
@@ -580,18 +593,21 @@ bool swift::escapeIdentifierInContext(Identifier name,
580
593
return isKeyword && keyword != " Self" ;
581
594
582
595
case PrintNameContext::TypeMember:
583
- return isKeyword || !canBeMemberName (keyword) || name.mustAlwaysBeEscaped ();
596
+ return isKeyword || !canBeMemberName (keyword) ||
597
+ (!isSpecializedCxxTemplate && name.mustAlwaysBeEscaped ());
584
598
585
599
case PrintNameContext::FunctionParameterExternal:
586
600
case PrintNameContext::FunctionParameterLocal:
587
601
case PrintNameContext::TupleElement:
588
- return !canBeArgumentLabel (keyword) || name.mustAlwaysBeEscaped ();
602
+ return !canBeArgumentLabel (keyword) ||
603
+ (!isSpecializedCxxTemplate && name.mustAlwaysBeEscaped ());
589
604
}
590
605
591
606
llvm_unreachable (" Unhandled PrintNameContext in switch." );
592
607
}
593
608
594
- void ASTPrinter::printName (Identifier Name, PrintNameContext Context) {
609
+ void ASTPrinter::printName (Identifier Name, PrintNameContext Context,
610
+ bool IsSpecializedCxxTemplate) {
595
611
callPrintNamePre (Context);
596
612
597
613
if (Name.empty ()) {
@@ -600,7 +616,8 @@ void ASTPrinter::printName(Identifier Name, PrintNameContext Context) {
600
616
return ;
601
617
}
602
618
603
- bool shouldEscapeIdentifier = escapeIdentifierInContext (Name, Context);
619
+ bool shouldEscapeIdentifier =
620
+ escapeIdentifierInContext (Name, Context, IsSpecializedCxxTemplate);
604
621
605
622
if (shouldEscapeIdentifier)
606
623
*this << " `" ;
@@ -3566,12 +3583,16 @@ void PrintAST::visitEnumDecl(EnumDecl *decl) {
3566
3583
} else {
3567
3584
Printer.printIntroducerKeyword (" enum" , Options, " " );
3568
3585
printContextIfNeeded (decl);
3569
- recordDeclLoc (decl,
3570
- [&]{
3571
- Printer.printName (decl->getName (), getTypeMemberPrintNameContext (decl));
3572
- }, [&]{ // Signature
3573
- printGenericDeclGenericParams (decl);
3574
- });
3586
+ recordDeclLoc (
3587
+ decl,
3588
+ [&] {
3589
+ Printer.printName (decl->getName (),
3590
+ getTypeMemberPrintNameContext (decl),
3591
+ isSpecializedCxxDecl (decl));
3592
+ },
3593
+ [&] { // Signature
3594
+ printGenericDeclGenericParams (decl);
3595
+ });
3575
3596
printInherited (decl);
3576
3597
printDeclGenericRequirements (decl);
3577
3598
}
@@ -3593,12 +3614,16 @@ void PrintAST::visitStructDecl(StructDecl *decl) {
3593
3614
} else {
3594
3615
Printer.printIntroducerKeyword (" struct" , Options, " " );
3595
3616
printContextIfNeeded (decl);
3596
- recordDeclLoc (decl,
3597
- [&]{
3598
- Printer.printName (decl->getName (), getTypeMemberPrintNameContext (decl));
3599
- }, [&]{ // Signature
3600
- printGenericDeclGenericParams (decl);
3601
- });
3617
+ recordDeclLoc (
3618
+ decl,
3619
+ [&] {
3620
+ Printer.printName (decl->getName (),
3621
+ getTypeMemberPrintNameContext (decl),
3622
+ isSpecializedCxxDecl (decl));
3623
+ },
3624
+ [&] { // Signature
3625
+ printGenericDeclGenericParams (decl);
3626
+ });
3602
3627
printInherited (decl);
3603
3628
printDeclGenericRequirements (decl);
3604
3629
}
@@ -3621,12 +3646,16 @@ void PrintAST::visitClassDecl(ClassDecl *decl) {
3621
3646
Printer.printIntroducerKeyword (
3622
3647
decl->isExplicitActor () ? " actor" : " class" , Options, " " );
3623
3648
printContextIfNeeded (decl);
3624
- recordDeclLoc (decl,
3625
- [&]{
3626
- Printer.printName (decl->getName (), getTypeMemberPrintNameContext (decl));
3627
- }, [&]{ // Signature
3628
- printGenericDeclGenericParams (decl);
3629
- });
3649
+ recordDeclLoc (
3650
+ decl,
3651
+ [&] {
3652
+ Printer.printName (decl->getName (),
3653
+ getTypeMemberPrintNameContext (decl),
3654
+ isSpecializedCxxDecl (decl));
3655
+ },
3656
+ [&] { // Signature
3657
+ printGenericDeclGenericParams (decl);
3658
+ });
3630
3659
3631
3660
printInherited (decl);
3632
3661
printDeclGenericRequirements (decl);
0 commit comments