Author: Deric C. Date: 2026-05-05T09:47:32-07:00 New Revision: 86b346da50a6629bdef1c49769870b10e20a2b01
URL: https://github.com/llvm/llvm-project/commit/86b346da50a6629bdef1c49769870b10e20a2b01 DIFF: https://github.com/llvm/llvm-project/commit/86b346da50a6629bdef1c49769870b10e20a2b01.diff LOG: [HLSL] For builtins aliases, apply implicit conversions before running custom type checking (#195365) Fixes https://github.com/llvm/llvm-project/issues/195329 by making HLSL builtin aliases apply implicit conversions before running custom type checking. After this PR: - There are no more size 1 vectors being passed and returned to/from aliased Clang builtins because they get truncated to scalars due to the HLSL alias builtin not having explicit size 1 vector overloads. - HLSL alias builtins no longer accept matrices unless they have explicit matrix overloads. Matrices get implicitly truncated to scalars and resolve to the scalar Clang builtin being aliased. - Many calls with mismatched vector sizes no longer error with `arguments are of different types` and instead follow Clang's overload resolution rules with respect to HLSL's implicit conversion sequences. (e.g., `dot(float3, float2)` -> `dot(float2, float2)` with warning) - Calls with implicitly-convertible types no longer error. They are now implicitly converted, and with a warning in some cases. (e.g., `f16tof32(bool)` -> `f16tof32(uint)` without warning, but `f16tof32(short)` -> `f16tof32(uint)` with warning). Assisted-by: Claude Opus 4.6 Added: Modified: clang/lib/Sema/SemaExpr.cpp clang/test/CodeGenHLSL/builtins/fma.hlsl clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl clang/test/SemaHLSL/BuiltIns/f16tof32-errors.hlsl clang/test/SemaHLSL/BuiltIns/f32tof16-errors.hlsl clang/test/SemaHLSL/BuiltIns/fma-errors.hlsl clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c494669420282..98062afae4577 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6076,9 +6076,14 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, SourceLocation RParenLoc, bool IsExecConfig) { // Bail out early if calling a builtin with custom typechecking. + // For HLSL builtin aliases, argument conversion is still needed because + // overload resolution may have selected a conversion sequence (e.g., + // vector-to-scalar truncation) that must be applied before the custom + // type checker runs. if (FDecl) if (unsigned ID = FDecl->getBuiltinID()) - if (Context.BuiltinInfo.hasCustomTypechecking(ID)) + if (Context.BuiltinInfo.hasCustomTypechecking(ID) && + !(Context.getLangOpts().HLSL && FDecl->hasAttr<BuiltinAliasAttr>())) return false; // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by @@ -7205,6 +7210,18 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Bail out early if calling a builtin with custom type checking. if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) { + // For HLSL builtin aliases, the call was resolved via overload resolution + // which may have selected a conversion sequence (e.g., vector-to-scalar + // truncation). Convert arguments to match the declared prototype before + // the custom type checker runs, otherwise the builtin will operate on + // the unconverted argument types. + if (getLangOpts().HLSL && FDecl && FDecl->hasAttr<BuiltinAliasAttr>()) { + if (const auto *P = FDecl->getType()->getAs<FunctionProtoType>()) { + if (ConvertArgumentsForCall(TheCall, Fn, FDecl, P, Args, RParenLoc, + IsExecConfig)) + return ExprError(); + } + } ExprResult E = CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall); if (!E.isInvalid() && Context.BuiltinInfo.isImmediate(BuiltinID)) E = CheckForImmediateInvocation(E, FDecl); diff --git a/clang/test/CodeGenHLSL/builtins/fma.hlsl b/clang/test/CodeGenHLSL/builtins/fma.hlsl index 3d9549197035d..93a2705c51634 100644 --- a/clang/test/CodeGenHLSL/builtins/fma.hlsl +++ b/clang/test/CodeGenHLSL/builtins/fma.hlsl @@ -25,10 +25,15 @@ double3 fma_double3(double3 a, double3 b, double3 c) { return fma(a, b, c); } // CHECK: ret <4 x double> double4 fma_double4(double4 a, double4 b, double4 c) { return fma(a, b, c); } -// CHECK-LABEL: define {{.*}} <1 x double> @{{.*}}fma_double1x1{{.*}}( -// CHECK: call reassoc nnan ninf nsz arcp afn <1 x double> @llvm.fma.v1f64(<1 x double> -// CHECK: ret <1 x double> -double1x1 fma_double1x1(double1x1 a, double1x1 b, double1x1 c) { +// No double1x1 fma overload exists, so overload resolution picks the scalar +// double overload. The double1x1 matrix arguments are truncated to scalar. +// CHECK-LABEL: define {{.*}} double @{{.*}}fma_double1x1{{.*}}( +// CHECK: %cast.mtrunc = extractelement <1 x double> +// CHECK: %cast.mtrunc{{[0-9]+}} = extractelement <1 x double> +// CHECK: %cast.mtrunc{{[0-9]+}} = extractelement <1 x double> +// CHECK: call reassoc nnan ninf nsz arcp afn double @llvm.fma.f64(double +// CHECK: ret double +double fma_double1x1(double1x1 a, double1x1 b, double1x1 c) { return fma(a, b, c); } diff --git a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl index bbe567b6d6ac1..2924639b92ca9 100644 --- a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl @@ -35,9 +35,11 @@ float2 test_scalar_first_arg3(float p0, float2 p1) { // expected-error@-1 {{call to 'clamp' is ambiguous}} } -float3 test_clamp_vector_size_last_arg_mismatch(float3 p0, float2 p1) { +// With implicit conversions, the float2 overload is selected and float3 args +// are truncated to float2. +float2 test_clamp_vector_size_last_arg_mismatch(float3 p0, float2 p1) { return clamp(p0, p0, p1); - // expected-error@-1 {{arguments are of diff erent types ('vector<[...], 3>' vs 'vector<[...], 2>')}} + // expected-warning@-1 2{{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} } typedef float float5 __attribute__((ext_vector_type(5))); diff --git a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl index f514a04eb9f49..0f62ba3dbdbf1 100644 --- a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl @@ -15,9 +15,11 @@ float test_dot_no_second_arg(float2 p0) { // expected-error@-1 {{no matching function for call to 'dot'}} } +// With implicit conversions, the float2 overload is selected and float3 is +// truncated to float2 with a warning (no longer a type-mismatch error). float test_dot_vector_size_mismatch(float3 p0, float2 p1) { return dot(p0, p1); - // expected-error@-1 {{arguments are of diff erent types ('vector<[...], 3>' vs 'vector<[...], 2>')}} + // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} } float test_dot_builtin_vector_size_mismatch(float3 p0, float2 p1) { diff --git a/clang/test/SemaHLSL/BuiltIns/f16tof32-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/f16tof32-errors.hlsl index 32abf5113fdd4..a39a9970a176c 100644 --- a/clang/test/SemaHLSL/BuiltIns/f16tof32-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/f16tof32-errors.hlsl @@ -77,58 +77,69 @@ float f16tof32_too_many_arg(uint p0) { // expected-error@-1 {{no matching function for call to 'f16tof32'}} } +// Overload resolution selects uint f16tof32(uint); bool is implicitly converted to uint. float f16tof32_bool(bool p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'bool')}} } +// Overload resolution selects an overload; bool3 is implicitly converted. float f16tof32_bool3(bool3 p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'bool3' (aka 'vector<bool, 3>'))}} + // expected-warning@-1 {{implicit conversion turns vector to scalar: 'vector<float, 3>' (vector of 3 'float' values) to 'float'}} } +// Overload resolution selects uint f16tof32(uint); short is implicitly converted to uint. float f16tof32_int16_t(short p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'short')}} + // expected-warning@-1 {{implicit conversion changes signedness: 'short' to 'uint' (aka 'unsigned int')}} } +// Overload resolution selects uint f16tof32(uint); unsigned short is implicitly converted to uint. float f16tof32_int16_t(unsigned short p0) { return f16tof32(p0); - // expected-error@-1 {{incorrect number of bits in integer (expected 32 bits, have 16)}} } +// Overload resolution selects uint f16tof32(uint); int is implicitly converted to uint. float f16tof32_int(int p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'int')}} + // expected-warning@-1 {{implicit conversion changes signedness: 'int' to 'uint' (aka 'unsigned int')}} } +// Overload resolution selects uint f16tof32(uint); long is implicitly converted to uint. float f16tof32_int64_t(long p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'long')}} + // expected-warning@-1 {{implicit conversion loses integer precision: 'long' to 'uint' (aka 'unsigned int')}} } +// Overload resolution selects an overload; int3 is implicitly converted. float2 f16tof32_int2_to_float2_promotion(int3 p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'int3' (aka 'vector<int, 3>'))}} + // expected-warning@-1 {{implicit conversion truncates vector: 'vector<float, 3>' (vector of 3 'float' values) to 'vector<float, 2>' (vector of 2 'float' values)}} + // expected-warning@-2 {{implicit conversion changes signedness: 'int3' (aka 'vector<int, 3>') to 'vector<uint, 3>' (vector of 3 'uint' values)}} } +// Overload resolution selects uint f16tof32(uint); half is implicitly converted to uint. float f16tof32_half(half p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'half')}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'half' to 'uint' (aka 'unsigned int')}} } +// Overload resolution selects an overload; half2 is implicitly converted. float f16tof32_half2(half2 p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'half2' (aka 'vector<half, 2>'))}} + // expected-warning@-1 {{implicit conversion turns vector to scalar: 'vector<float, 2>' (vector of 2 'float' values) to 'float'}} + // expected-warning@-2 {{implicit conversion turns floating-point number into integer: 'half2' (aka 'vector<half, 2>') to 'vector<uint, 2>' (vector of 2 'uint' values)}} } +// Overload resolution selects uint f16tof32(uint); float is implicitly converted to uint. float f16tof32_float(float p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'float')}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'float' to 'uint' (aka 'unsigned int')}} } +// Overload resolution selects uint f16tof32(uint); double is implicitly converted to uint. float f16tof32_double(double p0) { return f16tof32(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of unsigned integer types (was 'double')}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'double' to 'uint' (aka 'unsigned int')}} } diff --git a/clang/test/SemaHLSL/BuiltIns/f32tof16-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/f32tof16-errors.hlsl index 04479935754a6..b2b52f9b153ab 100644 --- a/clang/test/SemaHLSL/BuiltIns/f32tof16-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/f32tof16-errors.hlsl @@ -77,58 +77,66 @@ uint f32tof16_too_many_arg(uint p0) { // expected-error@-1 {{no matching function for call to 'f32tof16'}} } +// Overload resolution selects uint f32tof16(float); bool is implicitly converted to float. uint f32tof16_bool(bool p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'bool')}} } +// Overload resolution selects an overload; bool3 is implicitly converted. uint f32tof16_bool3(bool3 p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'bool3' (aka 'vector<bool, 3>'))}} + // expected-warning@-1 {{implicit conversion turns vector to scalar: 'vector<unsigned int, 3>' (vector of 3 'unsigned int' values) to 'unsigned int'}} } +// Overload resolution selects uint f32tof16(float); short is implicitly converted to float. uint f32tof16_int16_t(short p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'short')}} } +// Overload resolution selects uint f32tof16(float); unsigned short is implicitly converted to float. uint f32tof16_int16_t(unsigned short p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned short')}} } +// Overload resolution selects uint f32tof16(float); int is implicitly converted to float. uint f32tof16_int(int p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}} + // expected-warning@-1 {{implicit conversion from 'int' to 'float' may lose precision}} } +// Overload resolution selects uint f32tof16(float); long is implicitly converted to float. uint f32tof16_int64_t(long p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'long')}} + // expected-warning@-1 {{implicit conversion from 'long' to 'float' may lose precision}} } +// Overload resolution selects an overload; int3 is implicitly converted. uint2 f32tof16_int2_to_float2_promotion(int3 p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (aka 'vector<int, 3>'))}} + // expected-warning@-1 {{implicit conversion truncates vector: 'vector<unsigned int, 3>' (vector of 3 'unsigned int' values) to 'vector<unsigned int, 2>' (vector of 2 'unsigned int' values)}} + // expected-warning@-2 {{implicit conversion from 'int3' (aka 'vector<int, 3>') to 'vector<float, 3>' (vector of 3 'float' values) may lose precision}} } +// Overload resolution selects uint f32tof16(float); half is implicitly converted to float. uint f32tof16_half(half p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'half')}} } +// Overload resolution selects an overload; half2 is implicitly converted. uint f32tof16_half2(half2 p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'half2' (aka 'vector<half, 2>'))}} + // expected-warning@-1 {{implicit conversion turns vector to scalar: 'vector<unsigned int, 2>' (vector of 2 'unsigned int' values) to 'unsigned int'}} } +// Overload resolution selects uint f32tof16(float); uint is implicitly converted to float. uint f32tof16_float(uint p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'uint' (aka 'unsigned int'))}} + // expected-warning@-1 {{implicit conversion from 'uint' (aka 'unsigned int') to 'float' may lose precision}} } +// Overload resolution selects uint f32tof16(float); double is implicitly converted to float. uint f32tof16_double(double p0) { return f32tof16(p0); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'double')}} + // expected-warning@-1 {{implicit conversion loses floating-point precision: 'double' to 'float'}} } diff --git a/clang/test/SemaHLSL/BuiltIns/fma-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/fma-errors.hlsl index a454f2df4d508..e6a2dd6c052be 100644 --- a/clang/test/SemaHLSL/BuiltIns/fma-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/fma-errors.hlsl @@ -1,70 +1,88 @@ // RUN: %clang_cc1 -finclude-default-header -fnative-half-type -x hlsl \ -// RUN: -triple dxil-pc-shadermodel6.6-library %s \ +// RUN: -triple dxil-pc-shadermodel6.6-library %s -Wdouble-promotion \ // RUN: -emit-llvm-only -disable-llvm-passes -verify \ // RUN: -verify-ignore-unexpected=note // RUN: %clang_cc1 -finclude-default-header -fnative-half-type -x hlsl \ -// RUN: -triple spirv-unknown-vulkan-compute %s \ +// RUN: -triple spirv-unknown-vulkan-compute %s -Wdouble-promotion \ // RUN: -emit-llvm-only -disable-llvm-passes -verify \ // RUN: -verify-ignore-unexpected=note float bad_float(float a, float b, float c) { + // Overload resolution selects 'double fma(double, double, double)'; args promoted to double. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar, vector, or matrix of double type (was 'float')}} + // expected-warning@-1 3{{implicit conversion increases floating-point precision: 'float' to 'double'}} + // expected-warning@-2 {{implicit conversion loses floating-point precision: 'double' to 'float'}} } float2 bad_float2(float2 a, float2 b, float2 c) { + // Overload resolution selects 'double2 fma(double2, double2, double2)'; args promoted to double2. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar, vector, or matrix of double type (was 'float2' (aka 'vector<float, 2>'))}} + // expected-warning@-1 3{{implicit conversion increases floating-point precision: 'float2' (aka 'vector<float, 2>') to 'vector<double, 2>' (vector of 2 'double' values)}} + // expected-warning@-2 {{implicit conversion loses floating-point precision: 'vector<double, 2>' (vector of 2 'double' values) to 'vector<float, 2>' (vector of 2 'float' values)}} } float2x2 bad_float2x2(float2x2 a, float2x2 b, float2x2 c) { + // Overload resolution selects 'double2x2 fma(double2x2, double2x2, double2x2)'; args promoted. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar, vector, or matrix of double type (was 'float2x2' (aka 'matrix<float, 2, 2>'))}} + // expected-warning@-1 3{{implicit conversion increases floating-point precision: 'float2x2' (aka 'matrix<float, 2, 2>') to 'matrix<double, 2, 2>'}} + // expected-warning@-2 {{implicit conversion loses floating-point precision: 'matrix<double, 2, 2>' to 'matrix<float, 2, 2>'}} } half bad_half(half a, half b, half c) { + // Overload resolution selects 'double fma(double, double, double)'; args promoted to double. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar, vector, or matrix of double type (was 'half')}} + // expected-warning@-1 3{{implicit conversion increases floating-point precision: 'half' to 'double'}} + // expected-warning@-2 {{implicit conversion loses floating-point precision: 'double' to 'half'}} } half2 bad_half2(half2 a, half2 b, half2 c) { + // Overload resolution selects 'double2 fma(double2, double2, double2)'; args promoted. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar, vector, or matrix of double type (was 'half2' (aka 'vector<half, 2>'))}} + // expected-warning@-1 3{{implicit conversion increases floating-point precision: 'half2' (aka 'vector<half, 2>') to 'vector<double, 2>' (vector of 2 'double' values)}} + // expected-warning@-2 {{implicit conversion loses floating-point precision: 'vector<double, 2>' (vector of 2 'double' values) to 'vector<half, 2>' (vector of 2 'half' values)}} } half2x2 bad_half2x2(half2x2 a, half2x2 b, half2x2 c) { + // Overload resolution selects 'double2x2 fma(double2x2, double2x2, double2x2)'; args promoted. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar, vector, or matrix of double type (was 'half2x2' (aka 'matrix<half, 2, 2>'))}} + // expected-warning@-1 3{{implicit conversion increases floating-point precision: 'half2x2' (aka 'matrix<half, 2, 2>') to 'matrix<double, 2, 2>'}} + // expected-warning@-2 {{implicit conversion loses floating-point precision: 'matrix<double, 2, 2>' to 'matrix<half, 2, 2>'}} } double mixed_bad_second(double a, float b, double c) { + // Overload resolution selects 'double fma(double, double, double)'; float promoted to double. return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('double' vs 'float')}} + // expected-warning@-1 {{implicit conversion increases floating-point precision: 'float' to 'double'}} } double mixed_bad_third(double a, double b, half c) { + // Overload resolution selects 'double fma(double, double, double)'; half promoted to double. return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('double' vs 'half')}} + // expected-warning@-1 {{implicit conversion increases floating-point precision: 'half' to 'double'}} } double2 mixed_bad_second_vec(double2 a, float2 b, double2 c) { + // Overload resolution selects 'double2 fma(double2, double2, double2)'; float2 promoted. return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('vector<double, [...]>' vs 'vector<float, [...]>')}} + // expected-warning@-1 {{implicit conversion increases floating-point precision: 'float2' (aka 'vector<float, 2>') to 'vector<double, 2>' (vector of 2 'double' values)}} } double2 mixed_bad_third_vec(double2 a, double2 b, float2 c) { + // Overload resolution selects 'double2 fma(double2, double2, double2)'; float2 promoted. return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('vector<double, [...]>' vs 'vector<float, [...]>')}} + // expected-warning@-1 {{implicit conversion increases floating-point precision: 'float2' (aka 'vector<float, 2>') to 'vector<double, 2>' (vector of 2 'double' values)}} } double2x2 mixed_bad_second_mat(double2x2 a, float2x2 b, double2x2 c) { + // Overload resolution selects 'double2x2 fma(double2x2, double2x2, double2x2)'; float2x2 promoted. return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('matrix<double, [2 * ...]>' vs 'matrix<float, [2 * ...]>')}} + // expected-warning@-1 {{implicit conversion increases floating-point precision: 'float2x2' (aka 'matrix<float, 2, 2>') to 'matrix<double, 2, 2>'}} } double2x2 mixed_bad_third_mat(double2x2 a, double2x2 b, half2x2 c) { + // Overload resolution selects 'double2x2 fma(double2x2, double2x2, double2x2)'; half2x2 promoted. return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('matrix<double, [2 * ...]>' vs 'matrix<half, [2 * ...]>')}} + // expected-warning@-1 {{implicit conversion increases floating-point precision: 'half2x2' (aka 'matrix<half, 2, 2>') to 'matrix<double, 2, 2>'}} } double shape_mismatch_second(double a, double2 b, double c) { @@ -84,30 +102,40 @@ double2x2 shape_mismatch_scalar_mat(double2x2 a, double b, double2x2 c) { double2x2 shape_mismatch_vec_mat(double2x2 a, double2 b, double2x2 c) { return fma(a, b, c); - // expected-error@-1 {{arguments are of diff erent types ('double2x2' (aka 'matrix<double, 2, 2>') vs 'double2' (aka 'vector<double, 2>'))}} + // Overload resolution selects the scalar 'double fma(double, double, double)' + // overload; vector/matrix arguments are truncated to scalar. + // expected-warning@-3 {{implicit conversion turns matrix to scalar: 'double2x2' (aka 'matrix<double, 2, 2>') to 'double'}} + // expected-warning@-4 {{implicit conversion turns vector to scalar: 'double2' (aka 'vector<double, 2>') to 'double'}} + // expected-warning@-5 {{implicit conversion turns matrix to scalar: 'double2x2' (aka 'matrix<double, 2, 2>') to 'double'}} } int bad_int(int a, int b, int c) { + // Overload resolution selects 'double fma(double, double, double)'; ints promoted to double. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} } int2 bad_int2(int2 a, int2 b, int2 c) { + // Overload resolution selects 'double2 fma(double2, double2, double2)'; int2 promoted. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int2' (aka 'vector<int, 2>'))}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'vector<double, 2>' (vector of 2 'double' values) to 'vector<int, 2>' (vector of 2 'int' values)}} } bool bad_bool(bool a, bool b, bool c) { + // Overload resolution selects 'double fma(double, double, double)'; bools promoted to double. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'bool')}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'double' to 'bool'}} + // expected-warning@-2 {{implicit conversion turns floating-point number into bool: 'double' to 'bool'}} } bool2 bad_bool2(bool2 a, bool2 b, bool2 c) { + // Overload resolution selects 'double2 fma(double2, double2, double2)'; bool2 promoted. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'bool2' (aka 'vector<bool, 2>'))}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'vector<double, 2>' (vector of 2 'double' values) to 'vector<bool, 2>' (vector of 2 'bool' values)}} } bool2x2 bad_bool2x2(bool2x2 a, bool2x2 b, bool2x2 c) { + // Overload resolution selects 'double2x2 fma(double2x2, double2x2, double2x2)'; bool2x2 promoted. return fma(a, b, c); - // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'bool2x2' (aka 'matrix<bool, 2, 2>'))}} + // expected-warning@-1 {{implicit conversion turns floating-point number into integer: 'matrix<double, 2, 2>' to 'matrix<bool, 2, 2>'}} } diff --git a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl index 22720a4a37d02..bc82991eb3e6b 100644 --- a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl @@ -25,14 +25,18 @@ float2 test_lerp_vector_trunc_warn1(float3 p0) { // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} } +// With implicit conversions, the float2 overload is selected and float3 args +// are implicitly truncated to float2 (warnings instead of type-mismatch error). float2 test_lerp_vector_size_mismatch1(float3 p0, float2 p1) { return lerp(p0, p0, p1); - // expected-error@-1 {{all arguments to 'lerp' must have the same type}} + // expected-warning@-1 2{{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} } +// With implicit conversions, the float2 overload is selected and float3 args +// are implicitly truncated to float2 (warnings instead of type-mismatch error). float2 test_lerp_vector_size_mismatch2(float3 p0, float2 p1) { return lerp(p0, p1, p0); - // expected-error@-1 {{all arguments to 'lerp' must have the same type}} + // expected-warning@-1 2{{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} } float2 test_lerp_builtin_vector_size_mismatch_Arg1(float3 p0, float2 p1) { diff --git a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl index 0e9dda7055f98..3d39b5e7dfea6 100644 --- a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl @@ -20,9 +20,11 @@ float2 test_mad_no_second_arg(float2 p0) { // expected-error@-1 {{no matching function for call to 'mad'}} } +// With implicit conversions, the float2 overload is selected and float3 args +// are implicitly truncated to float2 (warnings instead of type-mismatch error). float2 test_mad_vector_size_mismatch(float3 p0, float2 p1) { return mad(p0, p0, p1); - // expected-error@-1 {{arguments are of diff erent types ('vector<[...], 3>' vs 'vector<[...], 2>')}} + // expected-warning@-1 2{{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} } float2 test_mad_builtin_vector_size_mismatch(float3 p0, float2 p1) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
