Author: Deric C. Date: 2026-04-15T10:43:04-07:00 New Revision: 83a0866d0faf96fd1e4bf2526acd9afdcb231a69
URL: https://github.com/llvm/llvm-project/commit/83a0866d0faf96fd1e4bf2526acd9afdcb231a69 DIFF: https://github.com/llvm/llvm-project/commit/83a0866d0faf96fd1e4bf2526acd9afdcb231a69.diff LOG: [HLSL] Mark vector and matrix constructor-turned-InitListExprs as ListInitializations (#192151) Fixes #189086 This PR fixes a bug for HLSL where vector and matrix constructors that have been turned into initializer lists via https://github.com/llvm/llvm-project/blob/18519f34650db7fc8e1885ac0293c1e9a5f1b071/clang/lib/Sema/SemaInit.cpp#L6993-L7000 were not marked with ListInitialization = true, which causes template re-instantiation to fail because the initialization with a InitListExpr gets classified as a InitializationKind::IK_Direct instead of a InitializationKind::IK_DirectList when ListInitialization is false. Assisted-by: Claude Opus 4.6 Added: clang/test/AST/HLSL/hlsl-constructors-template.hlsl Modified: clang/lib/Sema/SemaExprCXX.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 39c5e3b0671bb..e60d5d7748b44 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1674,7 +1674,15 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // CXXTemporaryObjectExpr. It's also weird that the functional cast // is sometimes handled by initialization and sometimes not. QualType ResultType = Result.get()->getType(); - SourceRange Locs = ListInitialization + // In HLSL, vector/matrix constructors have their arguments wrapped into an + // InitListExpr during initialization sequencing. Mark the resulting + // CXXFunctionalCastExpr as list-initialization so that during template + // re-instantiation, TreeTransform correctly passes the InitListExpr back + // through BuildCXXTypeConstructExpr with ListInitialization=true as opposed + // to false. + bool IsListInit = ListInitialization || + (getLangOpts().HLSL && isa<InitListExpr>(Result.get())); + SourceRange Locs = IsListInit ? SourceRange() : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); Result = CXXFunctionalCastExpr::Create( diff --git a/clang/test/AST/HLSL/hlsl-constructors-template.hlsl b/clang/test/AST/HLSL/hlsl-constructors-template.hlsl new file mode 100644 index 0000000000000..3dbbdb5e16a68 --- /dev/null +++ b/clang/test/AST/HLSL/hlsl-constructors-template.hlsl @@ -0,0 +1,169 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +// Verify that HLSL vector/matrix paren-syntax constructors inside template +// functions produce the correct AST after template instantiation. The key +// property is that the CXXFunctionalCastExpr wrapping an InitListExpr survives +// re-instantiation intact. + +typedef int int2 __attribute__((ext_vector_type(2))); +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); +typedef float float2x2 __attribute__((matrix_type(2, 2))); +typedef float float2x3 __attribute__((matrix_type(2, 3))); + +// Basic vector constructors in a template. +template<typename T> +void vector_constructors() { +// CHECK-LABEL: FunctionDecl {{.*}} used vector_constructors 'void ()' implicit_instantiation +// CHECK: VarDecl {{.*}} a 'int2':'vector<int, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'int2':'vector<int, 2>' functional cast to int2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'int2':'vector<int, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 +// CHECK: VarDecl {{.*}} b 'float3':'vector<float, 3>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float3':'vector<float, 3>' functional cast to float3 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float3':'vector<float, 3>' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00 + int2 a = int2(0, 0); + float3 b = float3(1.0f, 2.0f, 3.0f); +} + + +// Nested vector constructor: float4 built from a float2 + two scalars. +template<typename T> +void vector_constructors_nested() { +// CHECK-LABEL: FunctionDecl {{.*}} used vector_constructors_nested 'void ()' implicit_instantiation +// CHECK: VarDecl {{.*}} used v 'float2':'vector<float, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2':'vector<float, 2>' functional cast to float2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2':'vector<float, 2>' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK: VarDecl {{.*}} w 'float4':'vector<float, 4>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float4':'vector<float, 4>' functional cast to float4 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue Var {{.*}} 'v' 'float2':'vector<float, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue Var {{.*}} 'v' 'float2':'vector<float, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 4.000000e+00 + float2 v = float2(1.0f, 2.0f); + float4 w = float4(v, 3.0f, 4.0f); +} + +// Matrix constructor in a template. +template<typename T> +void matrix_constructors() { +// CHECK-LABEL: FunctionDecl {{.*}} used matrix_constructors 'void ()' implicit_instantiation +// CHECK: VarDecl {{.*}} m 'float2x2':'matrix<float, 2, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 4.000000e+00 + float2x2 m = float2x2(1.0f, 2.0f, 3.0f, 4.0f); +} + +// Nested matrix constructor: float2x2 built from a float2 + two scalars. +template<typename T> +void matrix_constructors_nested() { +// CHECK-LABEL: FunctionDecl {{.*}} used matrix_constructors_nested 'void ()' implicit_instantiation +// CHECK: VarDecl {{.*}} used v 'float2':'vector<float, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2':'vector<float, 2>' functional cast to float2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2':'vector<float, 2>' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK: VarDecl {{.*}} m 'float2x2':'matrix<float, 2, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue Var {{.*}} 'v' 'float2':'vector<float, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue Var {{.*}} 'v' 'float2':'vector<float, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 4.000000e+00 + float2 v = float2(1.0f, 2.0f); + float2x2 m = float2x2(v, 3.0f, 4.0f); +} + +// Vector from matrix: float4 built from a float2x2 (elementwise cast). +template<typename T> +void vector_from_matrix() { +// CHECK-LABEL: FunctionDecl {{.*}} used vector_from_matrix 'void ()' implicit_instantiation +// CHECK: VarDecl {{.*}} used m 'float2x2':'matrix<float, 2, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 4.000000e+00 +// CHECK: VarDecl {{.*}} v 'float4':'vector<float, 4>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float4':'vector<float, 4>' functional cast to float4 <HLSLElementwiseCast> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' <LValueToRValue> +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue Var {{.*}} 'm' 'float2x2':'matrix<float, 2, 2>' + float2x2 m = float2x2(1.0f, 2.0f, 3.0f, 4.0f); + float4 v = float4(m); +} + +// Matrix from matrix: float2x3 built from a float2x2 + two scalars. +template<typename T> +void matrix_from_matrix() { +// CHECK-LABEL: FunctionDecl {{.*}} used matrix_from_matrix 'void ()' implicit_instantiation +// CHECK: VarDecl {{.*}} used m 'float2x2':'matrix<float, 2, 2>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 4.000000e+00 +// CHECK: VarDecl {{.*}} n 'float2x3':'matrix<float, 2, 3>' cinit +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'float2x3':'matrix<float, 2, 3>' functional cast to float2x3 <NoOp> +// CHECK-NEXT: InitListExpr {{.*}} 'float2x3':'matrix<float, 2, 3>' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MatrixSubscriptExpr {{.*}} 'float' lvalue matrixcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue Var {{.*}} 'm' 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MatrixSubscriptExpr {{.*}} 'float' lvalue matrixcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue Var {{.*}} 'm' 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MatrixSubscriptExpr {{.*}} 'float' lvalue matrixcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue Var {{.*}} 'm' 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MatrixSubscriptExpr {{.*}} 'float' lvalue matrixcomponent +// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue Var {{.*}} 'm' 'float2x2':'matrix<float, 2, 2>' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 5.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 6.000000e+00 + float2x2 m = float2x2(1.0f, 2.0f, 3.0f, 4.0f); + float2x3 n = float2x3(m, 5.0f, 6.0f); +} + +// Instantiate the templates from a compute shader entry point. +[numthreads(1,1,1)] +void main() { + vector_constructors<int>(); + vector_constructors_nested<float>(); + matrix_constructors<int>(); + matrix_constructors_nested<int>(); + vector_from_matrix<int>(); + matrix_from_matrix<int>(); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
