@@ -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 || SD->hasBraces ())
654
+ 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 ()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
662
678
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
663
679
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
664
680
if (!Policy.SuppressSpecifiers ) {
681
+ if (const char *Lang = tryGetUnbracedLinkageLanguage (D)) {
682
+ // the "extern" specifier is implicit
683
+ assert (D->getStorageClass () == SC_None);
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,11 @@ 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
+ // the "extern" specifier is implicit
958
+ assert (D->getStorageClass () == SC_None);
959
+ Out << " extern \" " << Lang << " \" " ;
960
+ }
935
961
StorageClass SC = D->getStorageClass ();
936
962
if (SC != SC_None)
937
963
Out << VarDecl::getStorageClassSpecifierString (SC) << " " ;
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
961
987
962
988
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
963
989
!Policy.SuppressUnwrittenScope )
964
- MaybePrintTagKeywordIfSupressingScopes (Policy, T, Out);
990
+ maybePrintTagKeywordIfSupressingScopes (Policy, T, Out);
965
991
966
992
printDeclType (T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
967
993
D->getIdentifier ())
@@ -1064,6 +1090,8 @@ void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
1064
1090
1065
1091
void DeclPrinter::VisitEmptyDecl (EmptyDecl *D) {
1066
1092
prettyPrintAttributes (D);
1093
+ if (const char *Lang = tryGetUnbracedLinkageLanguage (D))
1094
+ Out << " extern \" " << Lang << " \" ;" ;
1067
1095
}
1068
1096
1069
1097
void DeclPrinter::VisitCXXRecordDecl (CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
1136
1164
}
1137
1165
1138
1166
void DeclPrinter::VisitLinkageSpecDecl (LinkageSpecDecl *D) {
1139
- const char *l;
1167
+ if (!D->hasBraces ()) {
1168
+ VisitDeclContext (D);
1169
+ return ;
1170
+ }
1171
+ const char *L;
1140
1172
if (D->getLanguage () == LinkageSpecLanguageIDs::C)
1141
- l = " C" ;
1173
+ L = " C" ;
1142
1174
else {
1143
1175
assert (D->getLanguage () == LinkageSpecLanguageIDs::CXX &&
1144
1176
" unknown language in linkage specification" );
1145
- l = " C++" ;
1177
+ L = " C++" ;
1146
1178
}
1147
-
1148
- Out << " extern \" " << l << " \" " ;
1149
- if (D->hasBraces ()) {
1150
- Out << " {\n " ;
1151
- VisitDeclContext (D);
1152
- Indent () << " }" ;
1153
- } else
1154
- Visit (*D->decls_begin ());
1179
+ Out << " extern \" " << L << " \" {\n " ;
1180
+ VisitDeclContext (D);
1181
+ Indent () << " }" ;
1155
1182
}
1156
1183
1157
1184
void DeclPrinter::printTemplateParameters (const TemplateParameterList *Params,
0 commit comments