@@ -1124,7 +1124,9 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
1124
1124
OS << T->getTypeConstraintConcept ()->getName ();
1125
1125
auto Args = T->getTypeConstraintArguments ();
1126
1126
if (!Args.empty ())
1127
- printTemplateArgumentList (OS, Args, Policy);
1127
+ printTemplateArgumentList (
1128
+ OS, Args, Policy,
1129
+ T->getTypeConstraintConcept ()->getTemplateParameters ());
1128
1130
OS << ' ' ;
1129
1131
}
1130
1132
switch (T->getKeyword ()) {
@@ -1226,7 +1228,9 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
1226
1228
IncludeStrongLifetimeRAII Strong (Policy);
1227
1229
OS << Spec->getIdentifier ()->getName ();
1228
1230
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs ();
1229
- printTemplateArgumentList (OS, TemplateArgs.asArray (), Policy);
1231
+ printTemplateArgumentList (
1232
+ OS, TemplateArgs.asArray (), Policy,
1233
+ Spec->getSpecializedTemplate ()->getTemplateParameters ());
1230
1234
OS << " ::" ;
1231
1235
} else if (const auto *Tag = dyn_cast<TagDecl>(DC)) {
1232
1236
if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl ())
@@ -1317,7 +1321,9 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
1317
1321
Args = TemplateArgs.asArray ();
1318
1322
}
1319
1323
IncludeStrongLifetimeRAII Strong (Policy);
1320
- printTemplateArgumentList (OS, Args, Policy);
1324
+ printTemplateArgumentList (
1325
+ OS, Args, Policy,
1326
+ Spec->getSpecializedTemplate ()->getTemplateParameters ());
1321
1327
}
1322
1328
1323
1329
spaceBeforePlaceHolder (OS);
@@ -1389,7 +1395,11 @@ void TypePrinter::printTemplateSpecializationBefore(
1389
1395
IncludeStrongLifetimeRAII Strong (Policy);
1390
1396
T->getTemplateName ().print (OS, Policy);
1391
1397
1392
- printTemplateArgumentList (OS, T->template_arguments (), Policy);
1398
+ const TemplateParameterList *TPL = nullptr ;
1399
+ if (TemplateDecl *TD = T->getTemplateName ().getAsTemplateDecl ())
1400
+ TPL = TD->getTemplateParameters ();
1401
+
1402
+ printTemplateArgumentList (OS, T->template_arguments (), Policy, TPL);
1393
1403
spaceBeforePlaceHolder (OS);
1394
1404
}
1395
1405
@@ -1789,9 +1799,159 @@ static void printArgument(const TemplateArgumentLoc &A,
1789
1799
return A.getArgument ().print (PP, OS);
1790
1800
}
1791
1801
1802
+ static bool isSubstitutedTemplateArgument (ASTContext &Ctx, TemplateArgument Arg,
1803
+ TemplateArgument Pattern,
1804
+ ArrayRef<TemplateArgument> Args,
1805
+ unsigned Depth);
1806
+
1807
+ static bool isSubstitutedType (ASTContext &Ctx, QualType T, QualType Pattern,
1808
+ ArrayRef<TemplateArgument> Args, unsigned Depth) {
1809
+ if (Ctx.hasSameType (T, Pattern))
1810
+ return true ;
1811
+
1812
+ // A type parameter matches its argument.
1813
+ if (auto *TTPT = Pattern->getAs <TemplateTypeParmType>()) {
1814
+ if (TTPT->getDepth () == Depth && TTPT->getIndex () < Args.size () &&
1815
+ Args[TTPT->getIndex ()].getKind () == TemplateArgument::Type) {
1816
+ QualType SubstArg = Ctx.getQualifiedType (
1817
+ Args[TTPT->getIndex ()].getAsType (), Pattern.getQualifiers ());
1818
+ return Ctx.hasSameType (SubstArg, T);
1819
+ }
1820
+ return false ;
1821
+ }
1822
+
1823
+ // FIXME: Recurse into array types.
1824
+
1825
+ // All other cases will need the types to be identically qualified.
1826
+ Qualifiers TQual, PatQual;
1827
+ T = Ctx.getUnqualifiedArrayType (T, TQual);
1828
+ Pattern = Ctx.getUnqualifiedArrayType (Pattern, PatQual);
1829
+ if (TQual != PatQual)
1830
+ return false ;
1831
+
1832
+ // Recurse into pointer-like types.
1833
+ {
1834
+ QualType TPointee = T->getPointeeType ();
1835
+ QualType PPointee = Pattern->getPointeeType ();
1836
+ if (!TPointee.isNull () && !PPointee.isNull ())
1837
+ return T->getTypeClass () == Pattern->getTypeClass () &&
1838
+ isSubstitutedType (Ctx, TPointee, PPointee, Args, Depth);
1839
+ }
1840
+
1841
+ // Recurse into template specialization types.
1842
+ if (auto *PTST =
1843
+ Pattern.getCanonicalType ()->getAs <TemplateSpecializationType>()) {
1844
+ TemplateName Template;
1845
+ ArrayRef<TemplateArgument> TemplateArgs;
1846
+ if (auto *TTST = T->getAs <TemplateSpecializationType>()) {
1847
+ Template = TTST->getTemplateName ();
1848
+ TemplateArgs = TTST->template_arguments ();
1849
+ } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
1850
+ T->getAsCXXRecordDecl ())) {
1851
+ Template = TemplateName (CTSD->getSpecializedTemplate ());
1852
+ TemplateArgs = CTSD->getTemplateArgs ().asArray ();
1853
+ } else {
1854
+ return false ;
1855
+ }
1856
+
1857
+ if (!isSubstitutedTemplateArgument (Ctx, Template, PTST->getTemplateName (),
1858
+ Args, Depth))
1859
+ return false ;
1860
+ if (TemplateArgs.size () != PTST->getNumArgs ())
1861
+ return false ;
1862
+ for (unsigned I = 0 , N = TemplateArgs.size (); I != N; ++I)
1863
+ if (!isSubstitutedTemplateArgument (Ctx, TemplateArgs[I], PTST->getArg (I),
1864
+ Args, Depth))
1865
+ return false ;
1866
+ return true ;
1867
+ }
1868
+
1869
+ // FIXME: Handle more cases.
1870
+ return false ;
1871
+ }
1872
+
1873
+ static bool isSubstitutedTemplateArgument (ASTContext &Ctx, TemplateArgument Arg,
1874
+ TemplateArgument Pattern,
1875
+ ArrayRef<TemplateArgument> Args,
1876
+ unsigned Depth) {
1877
+ Arg = Ctx.getCanonicalTemplateArgument (Arg);
1878
+ Pattern = Ctx.getCanonicalTemplateArgument (Pattern);
1879
+ if (Arg.structurallyEquals (Pattern))
1880
+ return true ;
1881
+
1882
+ if (Pattern.getKind () == TemplateArgument::Expression) {
1883
+ if (auto *DRE =
1884
+ dyn_cast<DeclRefExpr>(Pattern.getAsExpr ()->IgnoreParenImpCasts ())) {
1885
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl ()))
1886
+ return NTTP->getDepth () == Depth && Args.size () > NTTP->getIndex () &&
1887
+ Args[NTTP->getIndex ()].structurallyEquals (Arg);
1888
+ }
1889
+ }
1890
+
1891
+ if (Arg.getKind () != Pattern.getKind ())
1892
+ return false ;
1893
+
1894
+ if (Arg.getKind () == TemplateArgument::Type)
1895
+ return isSubstitutedType (Ctx, Arg.getAsType (), Pattern.getAsType (), Args,
1896
+ Depth);
1897
+
1898
+ if (Arg.getKind () == TemplateArgument::Template) {
1899
+ TemplateDecl *PatTD = Pattern.getAsTemplate ().getAsTemplateDecl ();
1900
+ if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(PatTD))
1901
+ return TTPD->getDepth () == Depth && Args.size () > TTPD->getIndex () &&
1902
+ Ctx.getCanonicalTemplateArgument (Args[TTPD->getIndex ()])
1903
+ .structurallyEquals (Arg);
1904
+ }
1905
+
1906
+ // FIXME: Handle more cases.
1907
+ return false ;
1908
+ }
1909
+
1910
+ // / Make a best-effort determination of whether the type T can be produced by
1911
+ // / substituting Args into the default argument of Param.
1912
+ static bool isSubstitutedDefaultArgument (ASTContext &Ctx, TemplateArgument Arg,
1913
+ const NamedDecl *Param,
1914
+ ArrayRef<TemplateArgument> Args,
1915
+ unsigned Depth) {
1916
+ // An empty pack is equivalent to not providing a pack argument.
1917
+ if (Arg.getKind () == TemplateArgument::Pack && Arg.pack_size () == 0 )
1918
+ return true ;
1919
+
1920
+ if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Param)) {
1921
+ return TTPD->hasDefaultArgument () &&
1922
+ isSubstitutedTemplateArgument (Ctx, Arg, TTPD->getDefaultArgument (),
1923
+ Args, Depth);
1924
+ } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
1925
+ return TTPD->hasDefaultArgument () &&
1926
+ isSubstitutedTemplateArgument (
1927
+ Ctx, Arg, TTPD->getDefaultArgument ().getArgument (), Args, Depth);
1928
+ } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
1929
+ return NTTPD->hasDefaultArgument () &&
1930
+ isSubstitutedTemplateArgument (Ctx, Arg, NTTPD->getDefaultArgument (),
1931
+ Args, Depth);
1932
+ }
1933
+ return false ;
1934
+ }
1935
+
1792
1936
template <typename TA>
1793
1937
static void printTo (raw_ostream &OS, ArrayRef<TA> Args,
1794
- const PrintingPolicy &Policy, bool SkipBrackets) {
1938
+ const PrintingPolicy &Policy, bool SkipBrackets,
1939
+ const TemplateParameterList *TPL) {
1940
+ // Drop trailing template arguments that match default arguments.
1941
+ if (TPL && Policy.SuppressDefaultTemplateArgs &&
1942
+ !Policy.PrintCanonicalTypes && !Args.empty () &&
1943
+ Args.size () <= TPL->size ()) {
1944
+ ASTContext &Ctx = TPL->getParam (0 )->getASTContext ();
1945
+ llvm::SmallVector<TemplateArgument, 8 > OrigArgs;
1946
+ for (const TA &A : Args)
1947
+ OrigArgs.push_back (getArgument (A));
1948
+ while (!Args.empty () &&
1949
+ isSubstitutedDefaultArgument (Ctx, getArgument (Args.back ()),
1950
+ TPL->getParam (Args.size () - 1 ),
1951
+ OrigArgs, TPL->getDepth ()))
1952
+ Args = Args.drop_back ();
1953
+ }
1954
+
1795
1955
const char *Comma = Policy.MSVCFormatting ? " ," : " , " ;
1796
1956
if (!SkipBrackets)
1797
1957
OS << ' <' ;
@@ -1806,7 +1966,7 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
1806
1966
if (Argument.getKind () == TemplateArgument::Pack) {
1807
1967
if (Argument.pack_size () && !FirstArg)
1808
1968
OS << Comma;
1809
- printTo (ArgOS, Argument.getPackAsArray (), Policy, true );
1969
+ printTo (ArgOS, Argument.getPackAsArray (), Policy, true , nullptr );
1810
1970
} else {
1811
1971
if (!FirstArg)
1812
1972
OS << Comma;
@@ -1839,20 +1999,23 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
1839
1999
1840
2000
void clang::printTemplateArgumentList (raw_ostream &OS,
1841
2001
const TemplateArgumentListInfo &Args,
1842
- const PrintingPolicy &Policy) {
1843
- return printTo (OS, Args.arguments (), Policy, false );
2002
+ const PrintingPolicy &Policy,
2003
+ const TemplateParameterList *TPL) {
2004
+ printTemplateArgumentList (OS, Args.arguments (), Policy, TPL);
1844
2005
}
1845
2006
1846
2007
void clang::printTemplateArgumentList (raw_ostream &OS,
1847
2008
ArrayRef<TemplateArgument> Args,
1848
- const PrintingPolicy &Policy) {
1849
- printTo (OS, Args, Policy, false );
2009
+ const PrintingPolicy &Policy,
2010
+ const TemplateParameterList *TPL) {
2011
+ printTo (OS, Args, Policy, false , TPL);
1850
2012
}
1851
2013
1852
2014
void clang::printTemplateArgumentList (raw_ostream &OS,
1853
2015
ArrayRef<TemplateArgumentLoc> Args,
1854
- const PrintingPolicy &Policy) {
1855
- printTo (OS, Args, Policy, false );
2016
+ const PrintingPolicy &Policy,
2017
+ const TemplateParameterList *TPL) {
2018
+ printTo (OS, Args, Policy, false , TPL);
1856
2019
}
1857
2020
1858
2021
std::string Qualifiers::getAsString () const {
0 commit comments