@@ -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 << " `" ;
@@ -3564,12 +3581,16 @@ void PrintAST::visitEnumDecl(EnumDecl *decl) {
3564
3581
} else {
3565
3582
Printer.printIntroducerKeyword (" enum" , Options, " " );
3566
3583
printContextIfNeeded (decl);
3567
- recordDeclLoc (decl,
3568
- [&]{
3569
- Printer.printName (decl->getName (), getTypeMemberPrintNameContext (decl));
3570
- }, [&]{ // Signature
3571
- printGenericDeclGenericParams (decl);
3572
- });
3584
+ recordDeclLoc (
3585
+ decl,
3586
+ [&] {
3587
+ Printer.printName (decl->getName (),
3588
+ getTypeMemberPrintNameContext (decl),
3589
+ isSpecializedCxxDecl (decl));
3590
+ },
3591
+ [&] { // Signature
3592
+ printGenericDeclGenericParams (decl);
3593
+ });
3573
3594
printInherited (decl);
3574
3595
printDeclGenericRequirements (decl);
3575
3596
}
@@ -3591,12 +3612,16 @@ void PrintAST::visitStructDecl(StructDecl *decl) {
3591
3612
} else {
3592
3613
Printer.printIntroducerKeyword (" struct" , Options, " " );
3593
3614
printContextIfNeeded (decl);
3594
- recordDeclLoc (decl,
3595
- [&]{
3596
- Printer.printName (decl->getName (), getTypeMemberPrintNameContext (decl));
3597
- }, [&]{ // Signature
3598
- printGenericDeclGenericParams (decl);
3599
- });
3615
+ recordDeclLoc (
3616
+ decl,
3617
+ [&] {
3618
+ Printer.printName (decl->getName (),
3619
+ getTypeMemberPrintNameContext (decl),
3620
+ isSpecializedCxxDecl (decl));
3621
+ },
3622
+ [&] { // Signature
3623
+ printGenericDeclGenericParams (decl);
3624
+ });
3600
3625
printInherited (decl);
3601
3626
printDeclGenericRequirements (decl);
3602
3627
}
@@ -3619,12 +3644,16 @@ void PrintAST::visitClassDecl(ClassDecl *decl) {
3619
3644
Printer.printIntroducerKeyword (
3620
3645
decl->isExplicitActor () ? " actor" : " class" , Options, " " );
3621
3646
printContextIfNeeded (decl);
3622
- recordDeclLoc (decl,
3623
- [&]{
3624
- Printer.printName (decl->getName (), getTypeMemberPrintNameContext (decl));
3625
- }, [&]{ // Signature
3626
- printGenericDeclGenericParams (decl);
3627
- });
3647
+ recordDeclLoc (
3648
+ decl,
3649
+ [&] {
3650
+ Printer.printName (decl->getName (),
3651
+ getTypeMemberPrintNameContext (decl),
3652
+ isSpecializedCxxDecl (decl));
3653
+ },
3654
+ [&] { // Signature
3655
+ printGenericDeclGenericParams (decl);
3656
+ });
3628
3657
3629
3658
printInherited (decl);
3630
3659
printDeclGenericRequirements (decl);
0 commit comments