@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
633
633
Out << Proto;
634
634
}
635
635
636
- static void MaybePrintTagKeywordIfSupressingScopes (PrintingPolicy &Policy,
636
+ static void maybePrintTagKeywordIfSupressingScopes (PrintingPolicy &Policy,
637
637
QualType T,
638
638
llvm::raw_ostream &Out) {
639
639
StringRef prefix = T->isClassType () ? " class "
@@ -643,6 +643,22 @@ static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
643
643
Out << prefix;
644
644
}
645
645
646
+ // / Return the language of the linkage spec of `D`, if applicable.
647
+ // /
648
+ // / \Return - "C" if `D` has been declared with unbraced `extern "C"`
649
+ // / - "C++" if `D` has been declared with unbraced `extern "C++"`
650
+ // / - nullptr in any other case
651
+ static const char *tryGetUnbracedLinkageLanguage (const Decl *D) {
652
+ const auto *SD = dyn_cast<LinkageSpecDecl>(D->getDeclContext ());
653
+ if (!SD) return nullptr ;
654
+ if (SD->hasBraces ()) return nullptr ;
655
+ if (SD->getLanguage () == LinkageSpecLanguageIDs::C)
656
+ return " C" ;
657
+ assert (SD->getLanguage () == LinkageSpecLanguageIDs::CXX &&
658
+ " unknown language in linkage specification" );
659
+ return " C++" ;
660
+ }
661
+
646
662
void DeclPrinter::VisitFunctionDecl (FunctionDecl *D) {
647
663
if (!D->getDescribedFunctionTemplate () &&
648
664
!D->isFunctionTemplateSpecialization ()) {
@@ -661,7 +677,12 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
661
677
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
662
678
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
663
679
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
680
+
664
681
if (!Policy.SuppressSpecifiers ) {
682
+ if (const char *lang = tryGetUnbracedLinkageLanguage (D)) {
683
+ assert (D->getStorageClass () == SC_None); // the "extern" specifier is implicit
684
+ Out << " extern \" " << lang << " \" " ;
685
+ }
665
686
switch (D->getStorageClass ()) {
666
687
case SC_None: break ;
667
688
case SC_Extern: Out << " extern " ; break ;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
807
828
}
808
829
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
809
830
!Policy.SuppressUnwrittenScope )
810
- MaybePrintTagKeywordIfSupressingScopes (Policy, AFT->getReturnType (),
831
+ maybePrintTagKeywordIfSupressingScopes (Policy, AFT->getReturnType (),
811
832
Out);
812
833
AFT->getReturnType ().print (Out, Policy, Proto);
813
834
Proto.clear ();
@@ -932,6 +953,10 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
932
953
: D->getASTContext ().getUnqualifiedObjCPointerType (D->getType ());
933
954
934
955
if (!Policy.SuppressSpecifiers ) {
956
+ if (const char *lang = tryGetUnbracedLinkageLanguage (D)) {
957
+ assert (D->getStorageClass () == SC_None); // the "extern" specifier is implicit
958
+ Out << " extern \" " << lang << " \" " ;
959
+ }
935
960
StorageClass SC = D->getStorageClass ();
936
961
if (SC != SC_None)
937
962
Out << VarDecl::getStorageClassSpecifierString (SC) << " " ;
@@ -961,7 +986,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
961
986
962
987
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
963
988
!Policy.SuppressUnwrittenScope )
964
- MaybePrintTagKeywordIfSupressingScopes (Policy, T, Out);
989
+ maybePrintTagKeywordIfSupressingScopes (Policy, T, Out);
965
990
966
991
printDeclType (T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
967
992
D->getIdentifier ())
@@ -1064,6 +1089,8 @@ void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
1064
1089
1065
1090
void DeclPrinter::VisitEmptyDecl (EmptyDecl *D) {
1066
1091
prettyPrintAttributes (D);
1092
+ if (const char *lang = tryGetUnbracedLinkageLanguage (D))
1093
+ Out << " extern \" " << lang << " \" ;" ;
1067
1094
}
1068
1095
1069
1096
void DeclPrinter::VisitCXXRecordDecl (CXXRecordDecl *D) {
@@ -1145,13 +1172,12 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
1145
1172
l = " C++" ;
1146
1173
}
1147
1174
1148
- Out << " extern \" " << l << " \" " ;
1149
1175
if (D->hasBraces ()) {
1150
- Out << " {\n " ;
1176
+ Out << " extern \" " << l << " \" {\n " ;
1151
1177
VisitDeclContext (D);
1152
1178
Indent () << " }" ;
1153
1179
} else
1154
- Visit (*D-> decls_begin () );
1180
+ VisitDeclContext (D );
1155
1181
}
1156
1182
1157
1183
void DeclPrinter::printTemplateParameters (const TemplateParameterList *Params,
0 commit comments