@@ -671,30 +671,58 @@ void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
671
671
672
672
void DiagnoseHLSLAvailability::RunOnTranslationUnit (
673
673
const TranslationUnitDecl *TU) {
674
+
674
675
// Iterate over all shader entry functions and library exports, and for those
675
676
// that have a body (definiton), run diag scan on each, setting appropriate
676
677
// shader environment context based on whether it is a shader entry function
677
- // or an exported function.
678
- for (auto &D : TU->decls ()) {
679
- const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
680
- if (!FD || !FD->isThisDeclarationADefinition ())
681
- continue ;
678
+ // or an exported function. Exported functions can be in namespaces and in
679
+ // export declarations so we need to scan those declaration contexts as well.
680
+ llvm::SmallVector<const DeclContext *, 8 > DeclContextsToScan;
681
+ DeclContextsToScan.push_back (TU);
682
+
683
+ while (!DeclContextsToScan.empty ()) {
684
+ const DeclContext *DC = DeclContextsToScan.pop_back_val ();
685
+ for (auto &D : DC->decls ()) {
686
+ // do not scan implicit declaration generated by the implementation
687
+ if (D->isImplicit ())
688
+ continue ;
689
+
690
+ // for namespace or export declaration add the context to the list to be
691
+ // scanned later
692
+ if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
693
+ DeclContextsToScan.push_back (llvm::dyn_cast<DeclContext>(D));
694
+ continue ;
695
+ }
682
696
683
- // shader entry point
684
- auto ShaderAttr = FD->getAttr <HLSLShaderAttr>();
685
- if (ShaderAttr) {
686
- SetShaderStageContext (ShaderAttr->getType ());
687
- RunOnFunction (FD);
688
- continue ;
689
- }
690
- // exported library function with definition
691
- // FIXME: tracking issue #92073
692
- #if 0
693
- if (FD->getFormalLinkage() == Linkage::External) {
694
- SetUnknownShaderStageContext();
695
- RunOnFunction(FD);
697
+ // skip over other decls or function decls without body
698
+ const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
699
+ if (!FD || !FD->isThisDeclarationADefinition ())
700
+ continue ;
701
+
702
+ // shader entry point
703
+ if (HLSLShaderAttr *ShaderAttr = FD->getAttr <HLSLShaderAttr>()) {
704
+ SetShaderStageContext (ShaderAttr->getType ());
705
+ RunOnFunction (FD);
706
+ continue ;
707
+ }
708
+ // exported library function
709
+ // FIXME: replace this loop with external linkage check once issue #92071
710
+ // is resolved
711
+ bool isExport = FD->isInExportDeclContext ();
712
+ if (!isExport) {
713
+ for (const auto *Redecl : FD->redecls ()) {
714
+ if (Redecl->isInExportDeclContext ()) {
715
+ isExport = true ;
716
+ break ;
717
+ }
718
+ }
719
+ }
720
+ if (isExport) {
721
+ SetUnknownShaderStageContext ();
722
+ RunOnFunction (FD);
723
+ continue ;
724
+ }
696
725
}
697
- #endif
698
726
}
699
727
}
700
728
@@ -707,8 +735,7 @@ void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
707
735
// For any CallExpr found during the traversal add it's callee to the top of
708
736
// the stack to be processed next. Functions already processed are stored in
709
737
// ScannedDecls.
710
- const FunctionDecl *FD = DeclsToScan.back ();
711
- DeclsToScan.pop_back ();
738
+ const FunctionDecl *FD = DeclsToScan.pop_back_val ();
712
739
713
740
// Decl was already scanned
714
741
const unsigned ScannedStages = GetScannedStages (FD);
0 commit comments