-
Notifications
You must be signed in to change notification settings - Fork 902
[202x] Enable auto return types
#8901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0943b55
1c227d3
b569a7c
d984ebe
fc3ef91
a995d87
ffa4159
c56f9ef
4e9ef8e
bcc525c
78725f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7480,12 +7480,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, | |||||||||
| NewFD->setVirtualAsWritten(true); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (getLangOpts().CPlusPlus14 && | ||||||||||
| if ((getLangOpts().CPlusPlus14) && | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unnecessary change? or is this meant to check if its hlsl too? I've made suggestions for both options below.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| NewFD->getReturnType()->isUndeducedType()) | ||||||||||
| Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (getLangOpts().CPlusPlus14 && | ||||||||||
| if ((getLangOpts().CPlusPlus14 || getLangOpts().HLSL) && // HLSL Change | ||||||||||
| (NewFD->isDependentContext() || | ||||||||||
| (isFriend && CurContext->isDependentContext())) && | ||||||||||
| NewFD->getReturnType()->isUndeducedType()) { | ||||||||||
|
llvm-beanz marked this conversation as resolved.
|
||||||||||
|
|
@@ -10908,8 +10908,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, | |||||||||
| if (FD) { | ||||||||||
| FD->setBody(Body); | ||||||||||
|
|
||||||||||
| if (getLangOpts().CPlusPlus14 && !FD->isInvalidDecl() && Body && | ||||||||||
| !FD->isDependentContext() && FD->getReturnType()->isUndeducedType()) { | ||||||||||
| // HLSL Change Begin - HLSL supports C++14-style deduced return types. | ||||||||||
| if ((getLangOpts().CPlusPlus14 || getLangOpts().HLSL) && | ||||||||||
| !FD->isInvalidDecl() && Body && !FD->isDependentContext() && | ||||||||||
| FD->getReturnType()->isUndeducedType()) { | ||||||||||
| // HLSL Change End | ||||||||||
| // If the function has a deduced result type but contains no 'return' | ||||||||||
| // statements, the result type as written must be exactly 'auto', and | ||||||||||
| // the deduced result type is 'void'. | ||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s -spirv | FileCheck %s | ||
|
|
||
| // Test that the 'auto' keyword can be used as a function return type and | ||
| // that the deduced type is used correctly when targeting SPIR-V. | ||
|
|
||
| // CHECK-DAG: [[INT:%[a-zA-Z0-9_]+]] = OpTypeInt 32 1 | ||
| // CHECK-DAG: [[FLOAT:%[a-zA-Z0-9_]+]] = OpTypeFloat 32 | ||
| // CHECK-DAG: [[V4FLOAT:%[a-zA-Z0-9_]+]] = OpTypeVector [[FLOAT]] 4 | ||
|
|
||
| // Function 'SquareInt' must return int. | ||
| // CHECK-DAG: %SquareInt = OpFunction [[INT]] None | ||
| // CHECK-DAG: %SquareFloat = OpFunction [[FLOAT]] None | ||
| // CHECK-DAG: %Scale = OpFunction [[V4FLOAT]] None | ||
| // CHECK-DAG: %WriteOutput = OpFunction %void None | ||
| // CHECK-DAG: %Sum = OpFunction [[FLOAT]] None | ||
|
|
||
| RWBuffer<float> output : register(u0); | ||
|
|
||
| auto SquareInt(int x) { | ||
| return x * x; | ||
| } | ||
|
|
||
| auto SquareFloat(float x) { | ||
| return x * x; | ||
| } | ||
|
|
||
| auto Scale(float4 v, float s) { | ||
| return v * s; | ||
| } | ||
|
|
||
| template <typename T> | ||
| auto Sum(T L, T R) { | ||
| return L + R; | ||
| } | ||
|
|
||
| auto WriteOutput(uint i, float v) { | ||
| output[i] = v; | ||
| } | ||
|
|
||
| [numthreads(1,1,1)] | ||
| void main() { | ||
| float4 v = float4(1, 2, 3, 4); | ||
| float4 s = Scale(v, 0.5f); | ||
| WriteOutput(0, (float)SquareInt(3) + Sum(SquareFloat(2.5f), s.x)); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // RUN: %dxc -T cs_6_0 -HV 202x -verify %s | ||
|
|
||
| // Test diagnostics for incorrect uses of 'auto' as a function return type. | ||
|
|
||
| // Inconsistent deduced types between return statements is an error. | ||
| auto BadDeduction(int x) { | ||
| if (x > 0) | ||
| return 1; // deduced as int | ||
| return 2.0f; // expected-error {{'auto' in return type deduced as 'float' here but deduced as 'int' in earlier return statement}} | ||
| } | ||
|
|
||
| // A function declared with 'auto' must be defined before it is used; a | ||
| // forward declaration alone is not sufficient for the call site. | ||
| auto ForwardOnly(int x); | ||
| void useForward() { | ||
| ForwardOnly(1); // expected-error {{function 'ForwardOnly' with deduced return type cannot be used before it is defined}} | ||
| } | ||
| // expected-note@-4 {{'ForwardOnly' declared here}} | ||
|
|
||
| // A recursive call to a function with deduced return type must occur after | ||
| // a return statement that allows the type to be deduced. | ||
| auto BadRecurse(int x) { | ||
| return BadRecurse(x - 1) + 1; // expected-error {{cannot be used before it is defined}} | ||
| } | ||
| // expected-note@-3 {{'BadRecurse' declared here}} | ||
|
|
||
| [numthreads(1,1,1)] | ||
| void main() { | ||
| BadDeduction(1); | ||
| BadRecurse(2); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // RUN: %dxc -T cs_6_0 -E main -HV 2016 -verify %s | ||
| // RUN: %dxc -T cs_6_0 -E main -HV 2017 -verify %s | ||
| // RUN: %dxc -T cs_6_0 -E main -HV 2018 -verify %s | ||
| // RUN: %dxc -T cs_6_0 -E main -HV 2021 -verify %s | ||
|
|
||
| // 'auto' is allowed as a function return type from HLSL 2016 onward, but | ||
| // using it before language mode 202x produces an extension warning. | ||
|
|
||
| RWBuffer<float> output : register(u0); | ||
|
|
||
| // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} | ||
| auto Square(int x) { | ||
| return x * x; | ||
| } | ||
|
|
||
| [numthreads(1,1,1)] | ||
| void main() { | ||
| output[0] = (float)Square(3); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| // RUN: %dxc -T cs_6_0 -E main - %s -verify | ||
| // RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s | FileCheck %s | ||
|
|
||
| // Test that the 'auto' keyword can be used as a function return type and | ||
| // that the deduced type matches C++14 [dcl.spec.auto] rules. | ||
|
|
||
| // CHECK-LABEL: define void @main() | ||
|
|
||
| // CHECK-LABEL: define internal <4 x float> @"\01?Scale | ||
| // CHECK: ret <4 x float> | ||
|
|
||
| // CHECK-LABEL: define internal void @"\01?WriteOutput | ||
| // CHECK: ret void | ||
|
|
||
| // CHECK-LABEL: define internal i32 @"\01?SquareInt | ||
| // CHECK: ret i32 | ||
|
|
||
| // CHECK-LABEL: define internal float @"\01?SquareFloat | ||
| // CHECK: ret float | ||
|
|
||
| // CHECK-LABEL: define internal float @"\01??$Sum | ||
| // CHECK ret float | ||
|
|
||
|
|
||
| // CHECK-LABEL: define internal float @"\01?Clamp01 | ||
| // CHECK: ret float | ||
|
|
||
| RWBuffer<float> output : register(u0); | ||
|
|
||
| // Deduces int from a single return statement. | ||
| // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} | ||
| auto SquareInt(int x) { | ||
| return x * x; | ||
| } | ||
|
|
||
| // Deduces float from a single return statement. | ||
| // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} | ||
| auto SquareFloat(float x) { | ||
| return x * x; | ||
| } | ||
|
|
||
| // Deduces float4 from a single return statement. | ||
| // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} | ||
| auto Scale(float4 v, float s) { | ||
| return v * s; | ||
| } | ||
|
|
||
| // Deduces void when no return statement is present. | ||
| // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} | ||
| auto WriteOutput(uint i, float v) { | ||
| output[i] = v; | ||
| } | ||
|
|
||
| // Multiple return statements with the same deduced type are allowed. | ||
| // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} | ||
| auto Clamp01(float v) { | ||
| if (v < 0.0f) | ||
| return 0.0f; | ||
| if (v > 1.0f) | ||
| return 1.0f; | ||
| return v; | ||
| } | ||
|
|
||
| // expected-warning@+2 {{'auto' type specifier is a HLSL 202x extension}} | ||
| template <typename T> | ||
| auto Sum(T L, T R) { | ||
| return L + R; | ||
| } | ||
|
|
||
| [numthreads(1,1,1)] | ||
| void main() { | ||
| float4 v = float4(1, 2, 3, 4); | ||
| float4 s = Scale(v, 0.5f); | ||
| WriteOutput(0, (float)SquareInt(3) + SquareFloat(2.5f) + Sum(s.x, Clamp01(1.5f))); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| // RUN: %dxc -T lib_6_6 -HV 202x -verify %s | ||
|
|
||
| // Test that deducing a return type that 'auto' cannot represent produces a | ||
| // diagnostic, mirroring the checks already performed for 'auto' variables | ||
| // (see auto-undeducible-types.hlsl and auto-no-subobject.hlsl). | ||
|
|
||
| Texture2D<float4> tex : register(t0); | ||
| Texture2DMS<float4> texMS : register(t1); | ||
|
|
||
| GlobalRootSignature grs = {"CBV(b0)"}; | ||
|
|
||
| // String literals cannot be deduced by 'auto'. | ||
| auto GetString() { | ||
| // expected-error@+1 {{'auto' cannot deduce type 'literal string'}} | ||
| return "abc"; | ||
| } | ||
|
|
||
| // The proxy types used for '.mips'/'.sample' subscript operators cannot be | ||
| // deduced by 'auto'. | ||
| auto GetMips() { | ||
| // expected-error@+1 {{'auto' cannot deduce type}} | ||
| return tex.mips; | ||
| } | ||
|
|
||
| auto GetMipsElement() { | ||
| // expected-error@+1 {{'auto' cannot deduce type}} | ||
| return tex.mips[0]; | ||
| } | ||
|
|
||
| auto GetSample() { | ||
| // expected-error@+1 {{'auto' cannot deduce type}} | ||
| return texMS.sample; | ||
| } | ||
|
|
||
| auto GetSampleElement() { | ||
| // expected-error@+1 {{'auto' cannot deduce type}} | ||
| return texMS.sample[0]; | ||
| } | ||
|
|
||
| // Subobjects cannot be deduced by 'auto'. | ||
| auto GetSubobject() { | ||
| // expected-error@+1 {{'auto' cannot deduce type 'GlobalRootSignature'}} | ||
| return grs; | ||
| } | ||
|
|
||
| // Fully subscripted mips/sample accesses deduce a normal, deducible type. | ||
| auto GetMipsValue() { | ||
| return tex.mips[0][int2(1, 2)]; | ||
| } | ||
|
|
||
| auto GetSampleValue() { | ||
| return texMS.sample[0][int2(1, 2)]; | ||
| } | ||
|
|
||
| auto GetDynamicResource() { | ||
| // expected-error@+1 {{'auto' cannot deduce type '.Resource'}} | ||
| return ResourceDescriptorHeap[0]; | ||
| } | ||
|
|
||
| auto GetDynamicSampler() { | ||
| // expected-error@+1 {{'auto' cannot deduce type '.Sampler'}} | ||
| return SamplerDescriptorHeap[0]; | ||
| } | ||
|
|
||
| auto GetDynamicResource2() { | ||
| return ((RWBuffer<float>)ResourceDescriptorHeap[0]); | ||
| } | ||
|
|
||
| auto GetDynamicResource(bool IsRW) { | ||
| if (IsRW) | ||
| return ((RWBuffer<float>)ResourceDescriptorHeap[0]); | ||
| // expected-error@+1 {{'auto' in return type deduced as 'Buffer<float>' here but deduced as 'RWBuffer<float>' in earlier return statement}} | ||
| return ((Buffer<float>)ResourceDescriptorHeap[0]); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.