@@ -4496,10 +4496,22 @@ SYCLIntegrationHeader::SYCLIntegrationHeader(bool _UnnamedLambdaSupport,
4496
4496
: UnnamedLambdaSupport(_UnnamedLambdaSupport), S(_S) {}
4497
4497
4498
4498
void SYCLIntegrationFooter::addVarDecl (const VarDecl *VD) {
4499
+ // Skip the dependent version of these variables, we only care about them
4500
+ // after instantiation.
4501
+ if (VD->getDeclContext ()->isDependentContext ())
4502
+ return ;
4499
4503
// Step 1: ensure that this is of the correct type-spec-constant template
4500
4504
// specialization).
4501
- if (!Util::isSyclSpecIdType (VD->getType ()))
4502
- return ;
4505
+ if (!Util::isSyclSpecIdType (VD->getType ())) {
4506
+ // Handle the case where this could be a deduced type, such as a deduction
4507
+ // guide. We have to do this here since this function, unlike most of the
4508
+ // rest of this file, is called during Sema instead of after it. We will
4509
+ // also have to filter out after deduction later.
4510
+ QualType Ty = VD->getType ().getCanonicalType ();
4511
+
4512
+ if (!Ty->isUndeducedType ())
4513
+ return ;
4514
+ }
4503
4515
// Step 2: ensure that this is a static member, or a namespace-scope.
4504
4516
// Note that isLocalVarDeclorParm excludes thread-local and static-local
4505
4517
// intentionally, as there is no way to 'spell' one of those in the
@@ -4541,26 +4553,162 @@ void SYCLIntegrationFooter::emitSpecIDName(raw_ostream &O, const VarDecl *VD) {
4541
4553
O << " " ;
4542
4554
}
4543
4555
4544
- bool SYCLIntegrationFooter::emit (raw_ostream &O) {
4556
+ template <typename BeforeFn, typename AfterFn>
4557
+ static void PrintNSHelper (BeforeFn Before, AfterFn After, raw_ostream &OS,
4558
+ const DeclContext *DC) {
4559
+ if (DC->isTranslationUnit ())
4560
+ return ;
4561
+
4562
+ const auto *CurDecl = cast<Decl>(DC);
4563
+ // Ensure we are in the canonical version, so that we know we have the 'full'
4564
+ // name of the thing.
4565
+ CurDecl = CurDecl->getCanonicalDecl ();
4566
+
4567
+ // We are intentionally skipping linkage decls and record decls. Namespaces
4568
+ // can appear in a linkage decl, but not a record decl, so we don't have to
4569
+ // worry about the names getting messed up from that. We handle record decls
4570
+ // later when printing the name of the thing.
4571
+ const auto *NS = dyn_cast<NamespaceDecl>(CurDecl);
4572
+ if (NS)
4573
+ Before (OS, NS);
4574
+
4575
+ if (const DeclContext *NewDC = CurDecl->getDeclContext ())
4576
+ PrintNSHelper (Before, After, OS, NewDC);
4577
+
4578
+ if (NS)
4579
+ After (OS, NS);
4580
+ }
4581
+
4582
+ static void PrintNamespaces (raw_ostream &OS, const DeclContext *DC) {
4583
+ PrintNSHelper ([](raw_ostream &OS, const NamespaceDecl *NS) {},
4584
+ [](raw_ostream &OS, const NamespaceDecl *NS) {
4585
+ if (NS->isInline ())
4586
+ OS << " inline " ;
4587
+ OS << " namespace " ;
4588
+ if (!NS->isAnonymousNamespace ())
4589
+ OS << NS->getName () << " " ;
4590
+ OS << " {\n " ;
4591
+ },
4592
+ OS, DC);
4593
+ }
4594
+
4595
+ static void PrintNSClosingBraces (raw_ostream &OS, const DeclContext *DC) {
4596
+ PrintNSHelper (
4597
+ [](raw_ostream &OS, const NamespaceDecl *NS) {
4598
+ OS << " } // " ;
4599
+ if (NS->isInline ())
4600
+ OS << " inline " ;
4601
+
4602
+ OS << " namespace " ;
4603
+ if (!NS->isAnonymousNamespace ())
4604
+ OS << NS->getName ();
4605
+
4606
+ OS << ' \n ' ;
4607
+ },
4608
+ [](raw_ostream &OS, const NamespaceDecl *NS) {}, OS, DC);
4609
+ }
4610
+
4611
+ static std::string EmitSpecIdShim (raw_ostream &OS, unsigned &ShimCounter,
4612
+ const std::string &LastShim,
4613
+ const NamespaceDecl *AnonNS) {
4614
+ std::string NewShimName =
4615
+ " __sycl_detail::__spec_id_shim_" + std::to_string (ShimCounter) + " ()" ;
4616
+ // Print opening-namespace
4617
+ PrintNamespaces (OS, Decl::castToDeclContext (AnonNS));
4618
+ OS << " namespace __sycl_detail {\n " ;
4619
+ OS << " static constexpr decltype(" << LastShim << " ) &__spec_id_shim_"
4620
+ << ShimCounter << " () {\n " ;
4621
+ OS << " return " << LastShim << " ;\n " ;
4622
+ OS << " }\n " ;
4623
+ OS << " } // namespace __sycl_detail \n " ;
4624
+ PrintNSClosingBraces (OS, Decl::castToDeclContext (AnonNS));
4625
+
4626
+ ++ShimCounter;
4627
+ return std::move (NewShimName);
4628
+ }
4629
+
4630
+ // Emit the list of shims required for a DeclContext, calls itself recursively.
4631
+ static void EmitSpecIdShims (raw_ostream &OS, unsigned &ShimCounter,
4632
+ const DeclContext *DC,
4633
+ std::string &NameForLastShim) {
4634
+ if (DC->isTranslationUnit ()) {
4635
+ NameForLastShim = " ::" + NameForLastShim;
4636
+ return ;
4637
+ }
4638
+
4639
+ const auto *CurDecl = cast<Decl>(DC)->getCanonicalDecl ();
4640
+
4641
+ // We skip linkage decls, since they don't modify the Qualified name.
4642
+ if (const auto *RD = dyn_cast<RecordDecl>(CurDecl)) {
4643
+ NameForLastShim = RD->getNameAsString () + " ::" + NameForLastShim;
4644
+ } else if (const auto *ND = dyn_cast<NamespaceDecl>(CurDecl)) {
4645
+ if (ND->isAnonymousNamespace ()) {
4646
+ // Print current shim, reset 'name for last shim'.
4647
+ NameForLastShim = EmitSpecIdShim (OS, ShimCounter, NameForLastShim, ND);
4648
+ } else {
4649
+ NameForLastShim = ND->getNameAsString () + " ::" + NameForLastShim;
4650
+ }
4651
+ } else {
4652
+ // FIXME: I don't believe there are other declarations that these variables
4653
+ // could possibly find themselves in. LinkageDecls don't change the
4654
+ // qualified name, so there is nothing to do here. At one point we should
4655
+ // probably convince ourselves that this is entire list and remove this
4656
+ // comment.
4657
+ assert ((isa<LinkageSpecDecl, ExternCContextDecl>(CurDecl)) &&
4658
+ " Unhandled decl type" );
4659
+ }
4660
+
4661
+ EmitSpecIdShims (OS, ShimCounter, CurDecl->getDeclContext (), NameForLastShim);
4662
+ }
4663
+
4664
+ // Emit the list of shims required for a variable declaration.
4665
+ // Returns a string containing the FQN of the 'top most' shim, including its
4666
+ // function call parameters.
4667
+ static std::string EmitSpecIdShims (raw_ostream &OS, unsigned &ShimCounter,
4668
+ const VarDecl *VD) {
4669
+ assert (VD->isInAnonymousNamespace () &&
4670
+ " Function assumes this is in an anonymous namespace" );
4671
+ std::string RelativeName = VD->getNameAsString ();
4672
+ EmitSpecIdShims (OS, ShimCounter, VD->getDeclContext (), RelativeName);
4673
+ return std::move (RelativeName);
4674
+ }
4675
+
4676
+ bool SYCLIntegrationFooter::emit (raw_ostream &OS) {
4545
4677
PrintingPolicy Policy{S.getLangOpts ()};
4546
4678
Policy.adjustForCPlusPlusFwdDecl ();
4547
4679
Policy.SuppressTypedefs = true ;
4548
4680
Policy.SuppressUnwrittenScope = true ;
4549
4681
4550
- for (const VarDecl *D : SpecConstants) {
4551
- O << " template<>\n " ;
4552
- O << " inline const char *get_spec_constant_symbolic_ID<" ;
4553
- // Emit the FQN for this, but we probably need to do some funny-business for
4554
- // anonymous namespaces.
4555
- D->printQualifiedName (O, Policy);
4556
- O << " >() {\n " ;
4557
- O << " return \" " ;
4558
- emitSpecIDName (O, D);
4559
- O << " \" ;\n " ;
4560
- O << " }\n " ;
4682
+ // Used to uniquely name the 'shim's as we generate the names in each
4683
+ // anonymous namespace.
4684
+ unsigned ShimCounter = 0 ;
4685
+ for (const VarDecl *VD : SpecConstants) {
4686
+ VD = VD->getCanonicalDecl ();
4687
+ if (VD->isInAnonymousNamespace ()) {
4688
+ std::string TopShim = EmitSpecIdShims (OS, ShimCounter, VD);
4689
+ OS << " namespace sycl {\n " ;
4690
+ OS << " namespace detail {\n " ;
4691
+ OS << " template<>\n " ;
4692
+ OS << " inline const char *get_spec_constant_symbolic_ID<" << TopShim
4693
+ << " >() {\n " ;
4694
+ OS << " return " << TopShim << " ;\n " ;
4695
+ } else {
4696
+ OS << " namespace sycl {\n " ;
4697
+ OS << " namespace detail {\n " ;
4698
+ OS << " template<>\n " ;
4699
+ OS << " inline const char *get_spec_constant_symbolic_ID<::" ;
4700
+ VD->printQualifiedName (OS, Policy);
4701
+ OS << " >() {\n " ;
4702
+ OS << " return \" " ;
4703
+ emitSpecIDName (OS, VD);
4704
+ OS << " \" ;\n " ;
4705
+ }
4706
+ OS << " }\n " ;
4707
+ OS << " } // namespace detail\n " ;
4708
+ OS << " } // namespace sycl\n " ;
4561
4709
}
4562
4710
4563
- O << " #include <CL/sycl/detail/spec_const_integration.hpp>\n " ;
4711
+ OS << " #include <CL/sycl/detail/spec_const_integration.hpp>\n " ;
4564
4712
return true ;
4565
4713
}
4566
4714
0 commit comments