Author: Sarah Spall Date: 2026-03-26T11:48:07-07:00 New Revision: 1eebbb066a3711330b535965a7701c6f6f52f332
URL: https://github.com/llvm/llvm-project/commit/1eebbb066a3711330b535965a7701c6f6f52f332 DIFF: https://github.com/llvm/llvm-project/commit/1eebbb066a3711330b535965a7701c6f6f52f332.diff LOG: [HLSL] Create XValue in HLSL list initialization if record is a prvalue (#186233) In the case where the record in an Init List expression is a prvalue create an xvalue so member accesses will be xvalues. This is in line with the C++ specification. The Clang code which generates the member field access however does not create an xvalue if the record is a prvalue, so we make the record an xvalue here. https://en.cppreference.com/w/cpp/language/value_category.html ``` is an xvalue expression: a.m, the member of object expression, where a is an rvalue and m is a non-static data member of an object type; ``` Adds Constant expression evaluation tests for Init list expressions which contain a cast. This test file is currently XFAILed on issue #188577 Closes #185911 --------- Co-authored-by: Deric C. <[email protected]> Added: clang/test/SemaHLSL/Types/InitListConstantExpr.hlsl Modified: clang/lib/Sema/SemaHLSL.cpp clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl clang/test/SemaHLSL/Language/InitListAST.hlsl Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index aebe284b2399a..3b7b12a884f43 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -5700,6 +5700,11 @@ class InitListTransformer { if (auto *RD = Ty->getAsCXXRecordDecl()) { llvm::SmallVector<CXXRecordDecl *> RecordDecls; RecordDecls.push_back(RD); + // If this is a prvalue create an xvalue so the member accesses + // will be xvalues. + if (E->isPRValue()) + E = new (Ctx) + MaterializeTemporaryExpr(Ty, E, /*BoundToLvalueReference=*/false); while (RecordDecls.back()->getNumBases()) { CXXRecordDecl *D = RecordDecls.back(); assert(D->getNumBases() == 1 && diff --git a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl index 3d7b8a906cdae..9c42da8962c2d 100644 --- a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl +++ b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl @@ -1146,6 +1146,169 @@ struct CustomResource { void case27(CustomResource a) { CustomResource b = {a}; } + +// Check cases with explicit casts + +// CHECK-LABEL: define hidden void @_Z6case289TwoFloats( +// CHECK-SAME: ptr noundef byval([[STRUCT_TWOFLOATS:%.*]]) align 1 [[TF:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TI:%.*]] = alloca [[STRUCT_TWOINTS:%.*]], align 1 +// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_TWOINTS]], align 1 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca [[STRUCT_TWOFLOATS]], align 1 +// CHECK-NEXT: [[REF_TMP6:%.*]] = alloca [[STRUCT_TWOINTS]], align 1 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca [[STRUCT_TWOFLOATS]], align 1 +// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TEMP]], ptr align 1 [[TF]], i32 8, i1 false) +// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [[STRUCT_TWOFLOATS]], ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds [[STRUCT_TWOFLOATS]], ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[GEP2]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP0]] to i32 +// CHECK-NEXT: store i32 [[CONV]], ptr [[GEP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[GEP3]], align 4 +// CHECK-NEXT: [[CONV4:%.*]] = fptosi float [[TMP1]] to i32 +// CHECK-NEXT: store i32 [[CONV4]], ptr [[GEP1]], align 4 +// CHECK-NEXT: [[Z5:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[Z5]], align 1 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[Z]], align 1 +// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TEMP7]], ptr align 1 [[TF]], i32 8, i1 false) +// CHECK-NEXT: [[GEP8:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP6]], i32 0, i32 0 +// CHECK-NEXT: [[GEP9:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP6]], i32 0, i32 1 +// CHECK-NEXT: [[GEP10:%.*]] = getelementptr inbounds [[STRUCT_TWOFLOATS]], ptr [[AGG_TEMP7]], i32 0, i32 0 +// CHECK-NEXT: [[GEP11:%.*]] = getelementptr inbounds [[STRUCT_TWOFLOATS]], ptr [[AGG_TEMP7]], i32 0, i32 1 +// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[GEP10]], align 4 +// CHECK-NEXT: [[CONV12:%.*]] = fptosi float [[TMP3]] to i32 +// CHECK-NEXT: store i32 [[CONV12]], ptr [[GEP8]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[GEP11]], align 4 +// CHECK-NEXT: [[CONV13:%.*]] = fptosi float [[TMP4]] to i32 +// CHECK-NEXT: store i32 [[CONV13]], ptr [[GEP9]], align 4 +// CHECK-NEXT: [[W14:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[REF_TMP6]], i32 0, i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[W14]], align 1 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[W]], align 1 +// CHECK-NEXT: ret void +// +void case28(TwoFloats TF) { + TwoInts TI = {(TwoInts)TF}; +} + +// CHECK-LABEL: define hidden void @_Z6case2910FourFloats( +// CHECK-SAME: ptr noundef byval([[STRUCT_FOURFLOATS:%.*]]) align 1 [[FF:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[INTS:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca [[STRUCT_FOURFLOATS]], align 1 +// CHECK-NEXT: [[REF_TMP7:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca [[STRUCT_FOURFLOATS]], align 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TEMP]], ptr align 1 [[FF]], i32 16, i1 false) +// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [2 x i32], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP]], i32 0, i32 0, i32 0 +// CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP]], i32 0, i32 0, i32 1 +// CHECK-NEXT: [[GEP4:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[GEP5:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[GEP2]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP0]] to i32 +// CHECK-NEXT: store i32 [[CONV]], ptr [[GEP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[GEP3]], align 4 +// CHECK-NEXT: [[CONV6:%.*]] = fptosi float [[TMP1]] to i32 +// CHECK-NEXT: store i32 [[CONV6]], ptr [[GEP1]], align 4 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [2 x i32], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[INTS]], align 4 +// CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[INTS]], i32 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TEMP8]], ptr align 1 [[FF]], i32 16, i1 false) +// CHECK-NEXT: [[GEP9:%.*]] = getelementptr inbounds [2 x i32], ptr [[REF_TMP7]], i32 0, i32 0 +// CHECK-NEXT: [[GEP10:%.*]] = getelementptr inbounds [2 x i32], ptr [[REF_TMP7]], i32 0, i32 1 +// CHECK-NEXT: [[GEP11:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP8]], i32 0, i32 0, i32 0 +// CHECK-NEXT: [[GEP12:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP8]], i32 0, i32 0, i32 1 +// CHECK-NEXT: [[GEP13:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP8]], i32 0, i32 1 +// CHECK-NEXT: [[GEP14:%.*]] = getelementptr inbounds [[STRUCT_FOURFLOATS]], ptr [[AGG_TEMP8]], i32 0, i32 2 +// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[GEP11]], align 4 +// CHECK-NEXT: [[CONV15:%.*]] = fptosi float [[TMP3]] to i32 +// CHECK-NEXT: store i32 [[CONV15]], ptr [[GEP9]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[GEP12]], align 4 +// CHECK-NEXT: [[CONV16:%.*]] = fptosi float [[TMP4]] to i32 +// CHECK-NEXT: store i32 [[CONV16]], ptr [[GEP10]], align 4 +// CHECK-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds nuw [2 x i32], ptr [[REF_TMP7]], i32 0, i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX17]], align 4 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[ARRAYINIT_ELEMENT]], align 4 +// CHECK-NEXT: ret void +// +void case29(FourFloats FF) { + int Ints[2] = {(int[2])FF}; +} + +// CHECK-LABEL: define hidden void @_Z6case30v( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARR:%.*]] = alloca [4 x float], align 4 +// CHECK-NEXT: [[TI:%.*]] = alloca [[STRUCT_TWOINTS:%.*]], align 1 +// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_TWOINTS]], align 1 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca [4 x float], align 4 +// CHECK-NEXT: [[REF_TMP8:%.*]] = alloca [[STRUCT_TWOINTS]], align 1 +// CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca [4 x float], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARR]], ptr align 4 @__const._Z6case30v.Arr, i32 16, i1 false) +// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_TEMP]], ptr align 4 [[ARR]], i32 16, i1 false) +// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[GEP4:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[GEP5:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP]], i32 0, i32 3 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[GEP2]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP0]] to i32 +// CHECK-NEXT: store i32 [[CONV]], ptr [[GEP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[GEP3]], align 4 +// CHECK-NEXT: [[CONV6:%.*]] = fptosi float [[TMP1]] to i32 +// CHECK-NEXT: store i32 [[CONV6]], ptr [[GEP1]], align 4 +// CHECK-NEXT: [[Z7:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[Z7]], align 1 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[Z]], align 1 +// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_TEMP9]], ptr align 4 [[ARR]], i32 16, i1 false) +// CHECK-NEXT: [[GEP10:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP8]], i32 0, i32 0 +// CHECK-NEXT: [[GEP11:%.*]] = getelementptr inbounds [[STRUCT_TWOINTS]], ptr [[REF_TMP8]], i32 0, i32 1 +// CHECK-NEXT: [[GEP12:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP9]], i32 0, i32 0 +// CHECK-NEXT: [[GEP13:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP9]], i32 0, i32 1 +// CHECK-NEXT: [[GEP14:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP9]], i32 0, i32 2 +// CHECK-NEXT: [[GEP15:%.*]] = getelementptr inbounds [4 x float], ptr [[AGG_TEMP9]], i32 0, i32 3 +// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[GEP12]], align 4 +// CHECK-NEXT: [[CONV16:%.*]] = fptosi float [[TMP3]] to i32 +// CHECK-NEXT: store i32 [[CONV16]], ptr [[GEP10]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[GEP13]], align 4 +// CHECK-NEXT: [[CONV17:%.*]] = fptosi float [[TMP4]] to i32 +// CHECK-NEXT: store i32 [[CONV17]], ptr [[GEP11]], align 4 +// CHECK-NEXT: [[W18:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[REF_TMP8]], i32 0, i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[W18]], align 1 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[W]], align 1 +// CHECK-NEXT: ret void +// +void case30() { + float Arr[4] = {1.0,2.0,3.0,4.0}; + TwoInts TI = {(TwoInts)Arr}; +} + +// CHECK-LABEL: define hidden void @_Z6case31v( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[F:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[SB:%.*]] = alloca [[STRUCT_SLICYBITS:%.*]], align 1 +// CHECK-NEXT: store float 1.000000e+00, ptr [[F]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP0]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[CONV]] to i8 +// CHECK-NEXT: store i8 [[TMP1]], ptr [[SB]], align 1 +// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_SLICYBITS]], ptr [[SB]], i32 0, i32 1 +// CHECK-NEXT: store i8 2, ptr [[W]], align 1 +// CHECK-NEXT: ret void +// +void case31() { + float F = 1.0; + SlicyBits SB = {(int)F, 2}; +} //. // CHECK: [[META3]] = !{} // CHECK: [[META4]] = !{i64 4} diff --git a/clang/test/SemaHLSL/Language/InitListAST.hlsl b/clang/test/SemaHLSL/Language/InitListAST.hlsl index 460ec38bb44af..63e6af61b124a 100644 --- a/clang/test/SemaHLSL/Language/InitListAST.hlsl +++ b/clang/test/SemaHLSL/Language/InitListAST.hlsl @@ -1059,3 +1059,120 @@ float case17() { float Floats[] = {Structs, Structs}; return Floats[7]; } + +// Tests which use explicit casts + +// CHECK-LABEL: Dumping case18 +// CHECK: VarDecl {{.*}} used TF 'TwoFloats' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats' +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.000000e+00 +// CHECK-NEXT: DeclStmt +// CHECK-NEXT: VarDecl {{.*}} used TI 'TwoInts' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'TwoInts' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' xvalue .Z +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'TwoInts' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'TwoInts' <HLSLElementwiseCast> +// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue Var {{.*}} 'TF' 'TwoFloats' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' xvalue .W +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'TwoInts' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'TwoInts' <HLSLElementwiseCast> +// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue Var {{.*}} 'TF' 'TwoFloats' +int case18() { + TwoFloats TF = {1.0,2.0}; + TwoInts TI = {(TwoInts)TF}; + return TI.Z; +} + +// CHECK-LABEL: Dumping case19 +// CHECK: VarDecl {{.*}} used FF 'FourFloats' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'FourFloats' +// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats' +// 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-NEXT: DeclStmt +// CHECK-NEXT: VarDecl {{.*}} used Ints 'int[4]' cinit +// CHECK-NEXT: ExprWithCleanups {{.*}} 'int[4]' +// CHECK-NEXT: InitListExpr {{.*}} 'int[4]' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' xvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay> +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'int[4]' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'int[4]' <HLSLElementwiseCast> +// CHECK-NEXT: DeclRefExpr {{.*}} 'FourFloats' lvalue Var {{.*}} 'FF' 'FourFloats' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' xvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay> +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'int[4]' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'int[4]' <HLSLElementwiseCast> +// CHECK-NEXT: DeclRefExpr {{.*}} 'FourFloats' lvalue Var {{.*}} 'FF' 'FourFloats' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' xvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay> +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'int[4]' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'int[4]' <HLSLElementwiseCast> +// CHECK-NEXT: DeclRefExpr {{.*}} 'FourFloats' lvalue Var {{.*}} 'FF' 'FourFloats' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' xvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay> +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'int[4]' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'int[4]' <HLSLElementwiseCast> +// CHECK-NEXT: DeclRefExpr {{.*}} 'FourFloats' lvalue Var {{.*}} 'FF' 'FourFloats' +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 +int case19() { + FourFloats FF = {1.0,2.0,3.0,4.0}; + int Ints[4] = {(int[4])FF}; + return Ints[0]; +} + +// CHECK-LABEL: Dumping case20 +// CHECK: VarDecl {{.*}} used Arr 'float[4]' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'float[4]' +// 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-NEXT: DeclStmt +// CHECK-NEXT: VarDecl {{.*}} used TI 'TwoInts' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'TwoInts' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' xvalue .Z +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'TwoInts' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'TwoInts' <HLSLElementwiseCast> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float[4]' <HLSLArrayRValue> part_of_explicit_cast +// CHECK-NEXT: DeclRefExpr {{.*}} 'float[4]' lvalue Var {{.*}} 'Arr' 'float[4]' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' xvalue .W +// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'TwoInts' xvalue +// CHECK-NEXT: CStyleCastExpr {{.*}} 'TwoInts' <HLSLElementwiseCast> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float[4]' <HLSLArrayRValue> part_of_explicit_cast +// CHECK-NEXT: DeclRefExpr {{.*}} 'float[4]' lvalue Var {{.*}} 'Arr' 'float[4]' +int case20() { + float Arr[4] = {1.0,2.0,3.0,4.0}; + TwoInts TI = {(TwoInts)Arr}; + return TI.Z; +} + +// CHECK-LABEL: Dumping case21 +// CHECK: VarDecl {{.*}} used F 'float' cinit +// CHECK-NEXT: {{.*}} 'float' 1.000000e+00 +// CHECK-NEXT: DeclStmt +// CHECK-NEXT: VarDecl {{.*}} used SB 'SlicyBits' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'SlicyBits' +// CHECK-NEXT: CStyleCastExpr {{.*}} 'int' <NoOp> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <FloatingToIntegral> part_of_explicit_cast +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> part_of_explicit_cast +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue Var {{.*}} 'F' 'float' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2 +int case21() { + float F = 1.0; + SlicyBits SB = {(int)F, 2}; + return SB.Z; +} diff --git a/clang/test/SemaHLSL/Types/InitListConstantExpr.hlsl b/clang/test/SemaHLSL/Types/InitListConstantExpr.hlsl new file mode 100644 index 0000000000000..c2797f5c8d94e --- /dev/null +++ b/clang/test/SemaHLSL/Types/InitListConstantExpr.hlsl @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -fnative-int16-type -std=hlsl202x -verify %s + +// expected-no-diagnostics +// XFAIL because of this issue: https://github.com/llvm/llvm-project/issues/188577 +// These tests hit an assert. +// XFAIL: * + +struct Base { + double D; + uint64_t2 U; + int16_t I : 5; + uint16_t I2: 5; +}; + +struct B1 { + float A; + float B; +}; + +struct B2 : B1 { + int C; + int D; + bool BB; +}; + +export void fn() { + + // splat from a vector of size 1 in an init list + constexpr int1 A1 = {1}; + constexpr uint64_t2 A72[2] = {(uint64_t2[2])A1}; + _Static_assert(A72[0][0] == 1, "Woo!"); + _Static_assert(A72[0][1] == 1, "Woo!"); + _Static_assert(A72[1][0] == 1, "Woo!"); + _Static_assert(A72[1][1] == 1, "Woo!"); + + // splat from a scalar inside an init list + constexpr double D = 97.6789; + constexpr B1 SB0 = {(B1)(D + 3.0)}; + _Static_assert(SB0.A == 100.6789, "Woo!"); + _Static_assert(SB0.B == 100.6789, "Woo!"); + + // result type struct from struct in an init list + constexpr B2 SB2 = {5.5, 6.5, 1000, 5000, false}; + constexpr Base SB3 = {(Base)SB2}; + _Static_assert(SB3.D == 5.5, "Woo!"); + _Static_assert(SB3.U[0] == 6, "Woo!"); + _Static_assert(SB3.U[1] == 1000, "Woo!"); + _Static_assert(SB3.I == 8, "Woo!"); + _Static_assert(SB3.I2 == 0, "Woo!"); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
