https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/97352
>From b67ecd20cc2c11f4f99c2d90c95fdbd988659947 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Wed, 26 Jun 2024 12:31:39 -0700 Subject: [PATCH 1/6] [HLSL] Implement `export` keyword Fixes #92812 --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Parse/ParseDeclCXX.cpp | 8 +++ clang/lib/Parse/Parser.cpp | 2 +- clang/lib/Sema/SemaModule.cpp | 32 ++++++++++++ clang/test/AST/HLSL/export.hlsl | 23 +++++++++ clang/test/CodeGenHLSL/export.hlsl | 20 ++++++++ clang/test/SemaHLSL/export.hlsl | 50 +++++++++++++++++++ 7 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 clang/test/AST/HLSL/export.hlsl create mode 100644 clang/test/CodeGenHLSL/export.hlsl create mode 100644 clang/test/SemaHLSL/export.hlsl diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 25a87078a5709..a2465ecc936e0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12265,6 +12265,9 @@ def warn_hlsl_availability_unavailable : Warning<err_unavailable.Summary>, InGroup<HLSLAvailability>, DefaultError; +def err_hlsl_export_not_on_function : Error< + "export declaration can only be used on functions">; + // Layout randomization diagnostics. def err_non_designated_init_used : Error< "a randomized struct can only be initialized with a designated initializer">; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5e3ee5f0579aa..226377e93fe56 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -445,6 +445,14 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { /// 'export' declaration /// 'export' '{' declaration-seq[opt] '}' /// +/// HLSL: Parse export function declaration. +/// +/// export-function-declaration: +/// 'export' function-declaration +/// +/// export-declaration-group: +/// 'export' '{' function-declaration-seq[opt] '}' +/// Decl *Parser::ParseExportDeclaration() { assert(Tok.is(tok::kw_export)); SourceLocation ExportLoc = ConsumeToken(); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 6d0cf7b174e50..ddc8aa9b49e64 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -970,7 +970,7 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, SingleDecl = ParseModuleImport(SourceLocation(), IS); } break; case tok::kw_export: - if (getLangOpts().CPlusPlusModules) { + if (getLangOpts().CPlusPlusModules || getLangOpts().HLSL) { ProhibitAttributes(Attrs); SingleDecl = ParseExportDeclaration(); break; diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index ad118ac90e4aa..e920b880ecb4d 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -851,6 +851,21 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, CurContext->addDecl(D); PushDeclContext(S, D); + if (getLangOpts().HLSL) { + // exported functions cannot be in an unnamed namespace + for (const DeclContext *DC = CurContext; DC; DC = DC->getLexicalParent()) { + if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) { + if (ND->isAnonymousNamespace()) { + Diag(ExportLoc, diag::err_export_within_anonymous_namespace); + Diag(ND->getLocation(), diag::note_anonymous_namespace); + D->setInvalidDecl(); + return D; + } + } + } + return D; + } + // C++2a [module.interface]p1: // An export-declaration shall appear only [...] in the purview of a module // interface unit. An export-declaration shall not appear directly or @@ -924,6 +939,23 @@ static bool checkExportedDeclContext(Sema &S, DeclContext *DC, /// Check that it's valid to export \p D. static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) { + // HLSL: export declaration is valid only on functions + if (S.getLangOpts().HLSL) { + auto *FD = dyn_cast<FunctionDecl>(D); + if (!FD) { + if (auto *ED2 = dyn_cast<ExportDecl>(D)) { + S.Diag(ED2->getBeginLoc(), diag::err_export_within_export); + if (auto *ED1 = dyn_cast<ExportDecl>(D->getDeclContext())) + S.Diag(ED1->getBeginLoc(), diag::note_export); + } + else { + S.Diag(D->getBeginLoc(), diag::err_hlsl_export_not_on_function); + } + D->setInvalidDecl(); + return false; + } + } + // C++20 [module.interface]p3: // [...] it shall not declare a name with internal linkage. bool HasName = false; diff --git a/clang/test/AST/HLSL/export.hlsl b/clang/test/AST/HLSL/export.hlsl new file mode 100644 index 0000000000000..69c4fb2b457ac --- /dev/null +++ b/clang/test/AST/HLSL/export.hlsl @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -x hlsl -ast-dump -o - %s | FileCheck %s + +// CHECK:ExportDecl 0x{{[0-9a-f]+}} <{{.*}}> col:1 +// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:13 used f1 'void ()' +// CHECK:CompoundStmt 0x{{[0-9a-f]+}} <{{.*}}> +export void f1() {} + +// CHECK:NamespaceDecl 0x{{[0-9a-f]+}} <{{.*}}> +// CHECK:ExportDecl 0x{{[0-9a-f]+}} <{{.*}}> col:3 +// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:15 used f2 'void ()' +// CHECK:CompoundStmt 0x{{[0-9a-f]+}} <{{.*}}> +namespace MyNamespace { + export void f2() {} +} + +// CHECK:ExportDecl 0x{{[0-9a-f]+}} <{{.*}}> +// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:10 used f3 'void ()' +// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:10 used f4 'void ()' +// CHECK:CompoundStmt 0x{{[0-9a-f]+}} <{{.*}}> +export { + void f3() {} + void f4() {} +} diff --git a/clang/test/CodeGenHLSL/export.hlsl b/clang/test/CodeGenHLSL/export.hlsl new file mode 100644 index 0000000000000..cea8875684b9e --- /dev/null +++ b/clang/test/CodeGenHLSL/export.hlsl @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define void @"?f1@@YAXXZ"() +export void f1() { +} + +// CHECK: define void @"?f2@MyNamespace@@YAXXZ"() +namespace MyNamespace { + export void f2() { + } +} + +export { +// CHECK: define void @"?f3@@YAXXZ"() +// CHECK: define void @"?f4@@YAXXZ"() + void f3() {} + void f4() {} +} \ No newline at end of file diff --git a/clang/test/SemaHLSL/export.hlsl b/clang/test/SemaHLSL/export.hlsl new file mode 100644 index 0000000000000..0cb9248f3f589 --- /dev/null +++ b/clang/test/SemaHLSL/export.hlsl @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify + +export void f1(); + +export void f1() {} + +namespace { // expected-note {{anonymous namespace begins here}} + export void f2(); // expected-error {{export declaration appears within anonymous namespace}} +} + +export void f3(); + +export { // expected-note {{export block begins here}} + void f4() {} + export void f5() {} // expected-error {{export declaration appears within another export declaration}} + int A; // expected-error {{export declaration can only be used on functions}} + namespace ns { // expected-error {{export declaration can only be used on functions}} + void f6(); + } +} + +void export f7() {} // expected-error {{expected unqualified-id}} + +export static void f8() {} // expected-error {{declaration of 'f8' with internal linkage cannot be exported}} + +export void f9(); // expected-note {{previous declaration is here}} +static void f9(); // expected-error {{static declaration of 'f9' follows non-static declaration}} + +static void f10(); // expected-note {{previous declaration is here}} +export void f10(); // expected-error {{cannot export redeclaration 'f10' here since the previous declaration has internal linkage}} + +export float V1; // expected-error {{export declaration can only be used on functions}} + +static export float V2; // expected-error{{expected unqualified-id}} + +export static float V3 = 0; // expected-error {{export declaration can only be used on functions}} + +export groupshared float V4; // expected-error {{export declaration can only be used on functions}} + +void f6() { + export int i; // expected-error {{expected expression}} +} + +export cbuffer CB { // expected-error {{export declaration can only be used on functions}} + int a; +} + +export template<typename T> void tf1(T t) {} // expected-error {{export declaration can only be used on functions}} + +void f5() export {} // expected-error {{expected function body after function declarator}} \ No newline at end of file >From 3edca8f3cecfd5a5ba269e97cb1e60f3c55eae5c Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 27 Jun 2024 17:16:24 -0700 Subject: [PATCH 2/6] Add availability diagnostic for export library functions Fixes #92073 --- clang/lib/Sema/SemaHLSL.cpp | 57 ++++++++++++------- .../Availability/avail-diag-default-lib.hlsl | 50 ++++++++++++++++ .../Availability/avail-diag-relaxed-lib.hlsl | 32 +++++++++++ .../Availability/avail-diag-strict-lib.hlsl | 50 ++++++++++++++++ 4 files changed, 168 insertions(+), 21 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index cc9c259858148..0b316e658fce3 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -679,30 +679,46 @@ void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD, void DiagnoseHLSLAvailability::RunOnTranslationUnit( const TranslationUnitDecl *TU) { + // Iterate over all shader entry functions and library exports, and for those // that have a body (definiton), run diag scan on each, setting appropriate // shader environment context based on whether it is a shader entry function - // or an exported function. - for (auto &D : TU->decls()) { - const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D); - if (!FD || !FD->isThisDeclarationADefinition()) - continue; + // or an exported function. Exported functions can be in namespaces and in + // export declarations so we need to scan those declaration contexts as well. + llvm::SmallVector<const DeclContext*, 8> DeclContextsToScan; + DeclContextsToScan.push_back(TU); + + while (!DeclContextsToScan.empty()) { + const DeclContext* DC = DeclContextsToScan.pop_back_val(); + for (auto &D : DC->decls()) { + // do not scan implicit declaration generated by the implementation + if (D->isImplicit()) + continue; + + // namespace or export declaration - add to the list to be scanned later + if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) { + DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D)); + continue; + } - // shader entry point - auto ShaderAttr = FD->getAttr<HLSLShaderAttr>(); - if (ShaderAttr) { - SetShaderStageContext(ShaderAttr->getType()); - RunOnFunction(FD); - continue; - } - // exported library function with definition - // FIXME: tracking issue #92073 -#if 0 - if (FD->getFormalLinkage() == Linkage::External) { - SetUnknownShaderStageContext(); - RunOnFunction(FD); + // skip over other decls or function decls without body + const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D); + if (!FD || !FD->isThisDeclarationADefinition()) + continue; + + // shader entry point + if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) { + SetShaderStageContext(ShaderAttr->getType()); + RunOnFunction(FD); + continue; + } + // exported library function + if (FD->isInExportDeclContext()) { + SetUnknownShaderStageContext(); + RunOnFunction(FD); + continue; + } } -#endif } } @@ -715,8 +731,7 @@ void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) { // For any CallExpr found during the traversal add it's callee to the top of // the stack to be processed next. Functions already processed are stored in // ScannedDecls. - const FunctionDecl *FD = DeclsToScan.back(); - DeclsToScan.pop_back(); + const FunctionDecl *FD = DeclsToScan.pop_back_val(); // Decl was already scanned const unsigned ScannedStages = GetScannedStages(FD); diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl index 515e4c5f9df03..19b06832c2218 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl @@ -110,6 +110,55 @@ class MyClass } }; +// Exported function without body +export void exportedFunctionUnused(float f); + +// Exported function with body - not used +export void exportedFunctionUnused(float f) { + // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUnused_fx_call + + // API with shader-stage-specific availability in unused exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(f); + float C = fz(f); +} + +// Exported function with body - called from main() which is a compute shader entry point +export void exportedFunctionUsed(float f) { + // expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUsed_fx_call + + // expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #exportedFunctionUsed_fy_call + + // expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #exportedFunctionUsed_fz_call +} + +namespace A { + namespace B { + export { + void exportedFunctionInNS(float x) { + // expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(x); // #exportedFunctionInNS_fx_call + + // API with shader-stage-specific availability in exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(x); + float C = fz(x); + } + } + } +} + // Shader entry point without body [shader("compute")] [numthreads(4,1,1)] @@ -126,5 +175,6 @@ float main() { float c = C.makeF(); float d = test((float)1.0); float e = test((half)1.0); + exportedFunctionUsed(1.0f); return a * b * c; } diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl index 6bd20450f8bfa..33d6e4816dda8 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl @@ -110,6 +110,37 @@ class MyClass } }; +// Exported function without body - not used +export void exportedFunctionUnused(float f); + +// Exported function with body - not used +export void exportedFunctionUnused(float f) { + // expected-warning@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUnused_fx_call + + // API with shader-stage-specific availability in unused exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(f); + float C = fz(f); +} + +// Exported function with body - called from main() which is a compute shader entry point +export void exportedFunctionUsed(float f) { + // expected-warning@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUsed_fx_call + + // expected-warning@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #exportedFunctionUsed_fy_call + + // expected-warning@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #exportedFunctionUsed_fz_call +} + // Shader entry point without body [shader("compute")] [numthreads(4,1,1)] @@ -126,5 +157,6 @@ float main() { float c = C.makeF(); float d = test((float)1.0); float e = test((half)1.0); + exportedFunctionUsed(1.0f); return a * b * c; } diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl index 4c9675051e570..bc1f006179a8d 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl @@ -129,6 +129,55 @@ class MyClass } }; +// Exported function without body - not used +export void exportedFunctionUnused(float f); + +// Exported function with body - not used +export void exportedFunctionUnused(float f) { + // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUnused_fx_call + + // API with shader-stage-specific availability in unused exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(f); + float C = fz(f); +} + +// Exported function with body - called from main() which is a compute shader entry point +export void exportedFunctionUsed(float f) { + // expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUsed_fx_call + + // expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #exportedFunctionUsed_fy_call + + // expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #exportedFunctionUsed_fz_call +} + +namespace A { + namespace B { + export { + void exportedFunctionInNS(float x) { + // expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(x); // #exportedFunctionInNS_fx_call + + // API with shader-stage-specific availability in exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(x); + float C = fz(x); + } + } + } +} + [shader("compute")] [numthreads(4,1,1)] float main() { @@ -138,5 +187,6 @@ float main() { float c = C.makeF(); float d = test((float)1.0); float e = test((half)1.0); + exportedFunctionUsed(1.0f); return a * b * c; } \ No newline at end of file >From 8a3092ca56f790bd182c09c04bbe5b6756fd3050 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 1 Jul 2024 13:56:35 -0700 Subject: [PATCH 3/6] Revert "[HLSL] Implement `export` keyword" This reverts commit b67ecd20cc2c11f4f99c2d90c95fdbd988659947. --- .../clang/Basic/DiagnosticSemaKinds.td | 3 -- clang/lib/Parse/ParseDeclCXX.cpp | 8 --- clang/lib/Parse/Parser.cpp | 2 +- clang/lib/Sema/SemaModule.cpp | 32 ------------ clang/test/AST/HLSL/export.hlsl | 23 --------- clang/test/CodeGenHLSL/export.hlsl | 20 -------- clang/test/SemaHLSL/export.hlsl | 50 ------------------- 7 files changed, 1 insertion(+), 137 deletions(-) delete mode 100644 clang/test/AST/HLSL/export.hlsl delete mode 100644 clang/test/CodeGenHLSL/export.hlsl delete mode 100644 clang/test/SemaHLSL/export.hlsl diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 64f7935d25d65..b8eafffd4650d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12324,9 +12324,6 @@ def warn_hlsl_availability_unavailable : Warning<err_unavailable.Summary>, InGroup<HLSLAvailability>, DefaultError; -def err_hlsl_export_not_on_function : Error< - "export declaration can only be used on functions">; - // Layout randomization diagnostics. def err_non_designated_init_used : Error< "a randomized struct can only be initialized with a designated initializer">; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index ce827c689beb7..2fc43a7e7926b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -445,14 +445,6 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { /// 'export' declaration /// 'export' '{' declaration-seq[opt] '}' /// -/// HLSL: Parse export function declaration. -/// -/// export-function-declaration: -/// 'export' function-declaration -/// -/// export-declaration-group: -/// 'export' '{' function-declaration-seq[opt] '}' -/// Decl *Parser::ParseExportDeclaration() { assert(Tok.is(tok::kw_export)); SourceLocation ExportLoc = ConsumeToken(); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 5ebe71e496a2e..71b87147e9a5f 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -970,7 +970,7 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, SingleDecl = ParseModuleImport(SourceLocation(), IS); } break; case tok::kw_export: - if (getLangOpts().CPlusPlusModules || getLangOpts().HLSL) { + if (getLangOpts().CPlusPlusModules) { ProhibitAttributes(Attrs); SingleDecl = ParseExportDeclaration(); break; diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index c8c07c0091903..98e7971dc0bf3 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -853,21 +853,6 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, CurContext->addDecl(D); PushDeclContext(S, D); - if (getLangOpts().HLSL) { - // exported functions cannot be in an unnamed namespace - for (const DeclContext *DC = CurContext; DC; DC = DC->getLexicalParent()) { - if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) { - if (ND->isAnonymousNamespace()) { - Diag(ExportLoc, diag::err_export_within_anonymous_namespace); - Diag(ND->getLocation(), diag::note_anonymous_namespace); - D->setInvalidDecl(); - return D; - } - } - } - return D; - } - // C++2a [module.interface]p1: // An export-declaration shall appear only [...] in the purview of a module // interface unit. An export-declaration shall not appear directly or @@ -941,23 +926,6 @@ static bool checkExportedDeclContext(Sema &S, DeclContext *DC, /// Check that it's valid to export \p D. static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) { - // HLSL: export declaration is valid only on functions - if (S.getLangOpts().HLSL) { - auto *FD = dyn_cast<FunctionDecl>(D); - if (!FD) { - if (auto *ED2 = dyn_cast<ExportDecl>(D)) { - S.Diag(ED2->getBeginLoc(), diag::err_export_within_export); - if (auto *ED1 = dyn_cast<ExportDecl>(D->getDeclContext())) - S.Diag(ED1->getBeginLoc(), diag::note_export); - } - else { - S.Diag(D->getBeginLoc(), diag::err_hlsl_export_not_on_function); - } - D->setInvalidDecl(); - return false; - } - } - // C++20 [module.interface]p3: // [...] it shall not declare a name with internal linkage. bool HasName = false; diff --git a/clang/test/AST/HLSL/export.hlsl b/clang/test/AST/HLSL/export.hlsl deleted file mode 100644 index 69c4fb2b457ac..0000000000000 --- a/clang/test/AST/HLSL/export.hlsl +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -x hlsl -ast-dump -o - %s | FileCheck %s - -// CHECK:ExportDecl 0x{{[0-9a-f]+}} <{{.*}}> col:1 -// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:13 used f1 'void ()' -// CHECK:CompoundStmt 0x{{[0-9a-f]+}} <{{.*}}> -export void f1() {} - -// CHECK:NamespaceDecl 0x{{[0-9a-f]+}} <{{.*}}> -// CHECK:ExportDecl 0x{{[0-9a-f]+}} <{{.*}}> col:3 -// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:15 used f2 'void ()' -// CHECK:CompoundStmt 0x{{[0-9a-f]+}} <{{.*}}> -namespace MyNamespace { - export void f2() {} -} - -// CHECK:ExportDecl 0x{{[0-9a-f]+}} <{{.*}}> -// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:10 used f3 'void ()' -// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <{{.*}}> col:10 used f4 'void ()' -// CHECK:CompoundStmt 0x{{[0-9a-f]+}} <{{.*}}> -export { - void f3() {} - void f4() {} -} diff --git a/clang/test/CodeGenHLSL/export.hlsl b/clang/test/CodeGenHLSL/export.hlsl deleted file mode 100644 index cea8875684b9e..0000000000000 --- a/clang/test/CodeGenHLSL/export.hlsl +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s - -// CHECK: define void @"?f1@@YAXXZ"() -export void f1() { -} - -// CHECK: define void @"?f2@MyNamespace@@YAXXZ"() -namespace MyNamespace { - export void f2() { - } -} - -export { -// CHECK: define void @"?f3@@YAXXZ"() -// CHECK: define void @"?f4@@YAXXZ"() - void f3() {} - void f4() {} -} \ No newline at end of file diff --git a/clang/test/SemaHLSL/export.hlsl b/clang/test/SemaHLSL/export.hlsl deleted file mode 100644 index 0cb9248f3f589..0000000000000 --- a/clang/test/SemaHLSL/export.hlsl +++ /dev/null @@ -1,50 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify - -export void f1(); - -export void f1() {} - -namespace { // expected-note {{anonymous namespace begins here}} - export void f2(); // expected-error {{export declaration appears within anonymous namespace}} -} - -export void f3(); - -export { // expected-note {{export block begins here}} - void f4() {} - export void f5() {} // expected-error {{export declaration appears within another export declaration}} - int A; // expected-error {{export declaration can only be used on functions}} - namespace ns { // expected-error {{export declaration can only be used on functions}} - void f6(); - } -} - -void export f7() {} // expected-error {{expected unqualified-id}} - -export static void f8() {} // expected-error {{declaration of 'f8' with internal linkage cannot be exported}} - -export void f9(); // expected-note {{previous declaration is here}} -static void f9(); // expected-error {{static declaration of 'f9' follows non-static declaration}} - -static void f10(); // expected-note {{previous declaration is here}} -export void f10(); // expected-error {{cannot export redeclaration 'f10' here since the previous declaration has internal linkage}} - -export float V1; // expected-error {{export declaration can only be used on functions}} - -static export float V2; // expected-error{{expected unqualified-id}} - -export static float V3 = 0; // expected-error {{export declaration can only be used on functions}} - -export groupshared float V4; // expected-error {{export declaration can only be used on functions}} - -void f6() { - export int i; // expected-error {{expected expression}} -} - -export cbuffer CB { // expected-error {{export declaration can only be used on functions}} - int a; -} - -export template<typename T> void tf1(T t) {} // expected-error {{export declaration can only be used on functions}} - -void f5() export {} // expected-error {{expected function body after function declarator}} \ No newline at end of file >From c8c6b5084bd1bb5f01d3e4edd2d8c932ff9ea0ad Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 1 Jul 2024 14:33:34 -0700 Subject: [PATCH 4/6] Update comment and add new line --- clang/lib/Sema/SemaHLSL.cpp | 3 ++- clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 5a4e69d2fee63..d22e6e8915067 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -687,7 +687,8 @@ void DiagnoseHLSLAvailability::RunOnTranslationUnit( if (D->isImplicit()) continue; - // namespace or export declaration - add to the list to be scanned later + // for namespace or export declaration add the context to the list to be + // scanned later if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) { DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D)); continue; diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl index bc1f006179a8d..cea3c33080d27 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl @@ -189,4 +189,4 @@ float main() { float e = test((half)1.0); exportedFunctionUsed(1.0f); return a * b * c; -} \ No newline at end of file +} >From 5b6e0a9696861da9e6fe64a9dcca5fcf776aeb95 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 1 Jul 2024 14:53:26 -0700 Subject: [PATCH 5/6] clang-format --- clang/lib/Sema/SemaHLSL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index d22e6e8915067..192238960e545 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -677,11 +677,11 @@ void DiagnoseHLSLAvailability::RunOnTranslationUnit( // shader environment context based on whether it is a shader entry function // or an exported function. Exported functions can be in namespaces and in // export declarations so we need to scan those declaration contexts as well. - llvm::SmallVector<const DeclContext*, 8> DeclContextsToScan; + llvm::SmallVector<const DeclContext *, 8> DeclContextsToScan; DeclContextsToScan.push_back(TU); while (!DeclContextsToScan.empty()) { - const DeclContext* DC = DeclContextsToScan.pop_back_val(); + const DeclContext *DC = DeclContextsToScan.pop_back_val(); for (auto &D : DC->decls()) { // do not scan implicit declaration generated by the implementation if (D->isImplicit()) >From 7fba9bfc8fbf0bde6354df165363503ea4d6f525 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 1 Jul 2024 18:25:42 -0700 Subject: [PATCH 6/6] Make sure we check all function redeclarations --- clang/lib/Sema/SemaHLSL.cpp | 13 ++++++++++++- .../Availability/avail-diag-default-lib.hlsl | 6 +++--- .../Availability/avail-diag-relaxed-lib.hlsl | 6 +++--- .../Availability/avail-diag-strict-lib.hlsl | 6 +++--- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 192238960e545..babb984995f13 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -706,7 +706,18 @@ void DiagnoseHLSLAvailability::RunOnTranslationUnit( continue; } // exported library function - if (FD->isInExportDeclContext()) { + // FIXME: replace this loop with external linkage check once issue #92071 + // is resolved + bool isExport = FD->isInExportDeclContext(); + if (!isExport) { + for (const auto *Redecl : FD->redecls()) { + if (Redecl->isInExportDeclContext()) { + isExport = true; + break; + } + } + } + if (isExport) { SetUnknownShaderStageContext(); RunOnFunction(FD); continue; diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl index 19b06832c2218..6bfc8577670cc 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl @@ -110,11 +110,11 @@ class MyClass } }; -// Exported function without body +// Exported function without body, not used export void exportedFunctionUnused(float f); -// Exported function with body - not used -export void exportedFunctionUnused(float f) { +// Exported function with body, without export, not used +void exportedFunctionUnused(float f) { // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} float A = fx(f); // #exportedFunctionUnused_fx_call diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl index 33d6e4816dda8..4c9783138f670 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl @@ -110,11 +110,11 @@ class MyClass } }; -// Exported function without body - not used +// Exported function without body, not used export void exportedFunctionUnused(float f); -// Exported function with body - not used -export void exportedFunctionUnused(float f) { +// Exported function with body, without export, not used +void exportedFunctionUnused(float f) { // expected-warning@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} float A = fx(f); // #exportedFunctionUnused_fx_call diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl index cea3c33080d27..c7be5afbc2d22 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl @@ -129,11 +129,11 @@ class MyClass } }; -// Exported function without body - not used +// Exported function without body, not used export void exportedFunctionUnused(float f); -// Exported function with body - not used -export void exportedFunctionUnused(float f) { +// Exported function with body, without export, not used +void exportedFunctionUnused(float f) { // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} float A = fx(f); // #exportedFunctionUnused_fx_call _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits