@@ -1857,6 +1857,38 @@ void SYCLIntegrationHeader::emitForwardClassDecls(
1857
1857
// template class Foo specialized by class Baz<Bar>, not a template
1858
1858
// class template <template <typename> class> class T as it should.
1859
1859
TemplateDecl *TD = Arg.getAsTemplate ().getAsTemplateDecl ();
1860
+ TemplateParameterList *TemplateParams = TD->getTemplateParameters ();
1861
+ for (NamedDecl *P : *TemplateParams) {
1862
+ // If template template paramter type has an enum value template
1863
+ // parameter, forward declaration of enum type is required. Only enum
1864
+ // values (not types) need to be handled. For example, consider the
1865
+ // following kernel name type:
1866
+ //
1867
+ // template <typename EnumTypeOut, template <EnumValueIn EnumValue,
1868
+ // typename TypeIn> class T> class Foo;
1869
+ //
1870
+ // The correct specialization for Foo (with enum type) is:
1871
+ // Foo<EnumTypeOut, Baz>, where Baz is a template class.
1872
+ //
1873
+ // Therefore the forward class declarations generated in the
1874
+ // integration header are:
1875
+ // template <EnumValueIn EnumValue, typename TypeIn> class Baz;
1876
+ // template <typename EnumTypeOut, template <EnumValueIn EnumValue,
1877
+ // typename EnumTypeIn> class T> class Foo;
1878
+ //
1879
+ // This requires the following enum forward declarations:
1880
+ // enum class EnumTypeOut : int; (Used to template Foo)
1881
+ // enum class EnumValueIn : int; (Used to template Baz)
1882
+ if (NonTypeTemplateParmDecl *TemplateParam =
1883
+ dyn_cast<NonTypeTemplateParmDecl>(P)) {
1884
+ QualType T = TemplateParam->getType ();
1885
+ if (const auto *ET = T->getAs <EnumType>()) {
1886
+ const EnumDecl *ED = ET->getDecl ();
1887
+ if (!checkEnumTemplateParameter (ED, Diag, KernelLocation))
1888
+ emitFwdDecl (O, ED, KernelLocation);
1889
+ }
1890
+ }
1891
+ }
1860
1892
if (Printed.insert (TD).second ) {
1861
1893
emitFwdDecl (O, TD, KernelLocation);
1862
1894
}
@@ -1923,6 +1955,11 @@ static void printArgument(ASTContext &Ctx, raw_ostream &ArgOS,
1923
1955
ArgOS << getKernelNameTypeString (T, Ctx, TypePolicy);
1924
1956
break ;
1925
1957
}
1958
+ case TemplateArgument::ArgKind::Template: {
1959
+ TemplateDecl *TD = Arg.getAsTemplate ().getAsTemplateDecl ();
1960
+ ArgOS << TD->getQualifiedNameAsString ();
1961
+ break ;
1962
+ }
1926
1963
default :
1927
1964
Arg.print (P, ArgOS);
1928
1965
}
0 commit comments