Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion tools/clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ def warn_cxx98_compat_trailing_return_type : Warning<
"trailing return types are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def ext_auto_type_specifier : ExtWarn<
"'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
"'auto' type specifier is a %select{C++11|HLSL 202x}0 extension">,
InGroup<CXX11>;
def warn_auto_storage_class : Warning<
"'auto' storage class specifier is redundant and incompatible with C++11">,
InGroup<CXX11Compat>, DefaultIgnore;
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/include/clang/Lex/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ class Token {
// HLSL Change Starts
bool isHLSLReserved() const {
return is(tok::kw___is_signed) || is(tok::kw___declspec) ||
is(tok::kw___forceinline) || is(tok::kw_auto) || is(tok::kw_catch) ||
is(tok::kw___forceinline) || is(tok::kw_catch) ||
is(tok::kw_const_cast) || is(tok::kw_delete) ||
is(tok::kw_dynamic_cast) || is(tok::kw_enum) ||
is(tok::kw_explicit) || is(tok::kw_friend) || is(tok::kw_goto) ||
Expand Down
8 changes: 6 additions & 2 deletions tools/clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3918,8 +3918,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
// HLSL Change Ends
case tok::kw_auto:
if (getLangOpts().HLSL) { goto HLSLReservedKeyword; } // HLSL Change - auto is reserved for HLSL
if (getLangOpts().CPlusPlus11) {
// HLSL Change Begin - auto is reserved for HLSL 2015 and earlier.
if (getLangOpts().HLSL &&
getLangOpts().HLSLVersion <= hlsl::LangStd::v2015)
goto HLSLReservedKeyword;
// HLSL Change End
if (getLangOpts().CPlusPlus11 || getLangOpts().HLSL) { // HLSL Change
if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
Expand Down
10 changes: 8 additions & 2 deletions tools/clang/lib/Sema/DeclSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,8 +1158,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
}
// Diagnose if we've recovered from an ill-formed 'auto' storage class
// specifier in a pre-C++11 dialect of C++.
if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
Diag(D, TSTLoc, diag::ext_auto_type_specifier);
// HLSL Change Begin - HLSL supports 'auto' as a type specifier in 202x+.
if (!(PP.getLangOpts().CPlusPlus11 ||
(PP.getLangOpts().HLSL &&
PP.getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) &&
TypeSpecType == TST_auto)
Diag(D, TSTLoc, diag::ext_auto_type_specifier)
<< /* HLSL */ PP.getLangOpts().HLSL;
// HLSL Change End
if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 &&
StorageClassSpec == SCS_auto)
Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
Expand Down
1 change: 0 additions & 1 deletion tools/clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9047,7 +9047,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,

// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
assert(!getLangOpts().HLSL && "auto types are not supported - merge type below is inconsequential"); // HLSL Change
if (VarDecl *Old = VDecl->getPreviousDecl()) {
// We never need to merge the type, because we cannot form an incomplete
// array of auto, nor deduce such a type.
Expand Down
51 changes: 51 additions & 0 deletions tools/clang/test/CodeGenSPIRV/var.auto.deduction.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s -spirv | FileCheck %s

// Test that the 'auto' keyword can be used to declare variables with inferred
// types from initialization expressions when targeting SPIR-V.

// CHECK: [[INT:%[a-zA-Z0-9_]+]] = OpTypeInt 32 1
// CHECK: [[INT_1:%[a-zA-Z0-9_]+]] = OpConstant [[INT]] 1
// CHECK: [[FLOAT:%[a-zA-Z0-9_]+]] = OpTypeFloat 32
// CHECK: [[FLOAT_2:%[a-zA-Z0-9_]+]] = OpConstant [[FLOAT]] 2
// CHECK: [[BOOL:%[a-zA-Z0-9_]+]] = OpTypeBool
// CHECK: [[TRUE:%[a-zA-Z0-9_]+]] = OpConstantTrue [[BOOL]]
// CHECK: [[V4FLOAT:%[a-zA-Z0-9_]+]] = OpTypeVector [[FLOAT]] 4
// CHECK: [[VEC_CONST:%[a-zA-Z0-9_]+]] = OpConstantComposite [[V4FLOAT]] {{%[a-zA-Z0-9_]+}} [[FLOAT_2]] {{%[a-zA-Z0-9_]+}} {{%[a-zA-Z0-9_]+}}

// CHECK: [[PTR_INT:%_ptr_Function_int]] = OpTypePointer Function [[INT]]
// CHECK: [[PTR_FLOAT:%_ptr_Function_float]] = OpTypePointer Function [[FLOAT]]
// CHECK: [[PTR_BOOL:%_ptr_Function_bool]] = OpTypePointer Function [[BOOL]]
// CHECK: [[PTR_V4FLOAT:%_ptr_Function_v4float]] = OpTypePointer Function [[V4FLOAT]]

// CHECK: %a = OpVariable [[PTR_INT]] Function
// CHECK: %b = OpVariable [[PTR_FLOAT]] Function
// CHECK: %c = OpVariable [[PTR_BOOL]] Function
// CHECK: %d = OpVariable [[PTR_V4FLOAT]] Function
// CHECK: %sum = OpVariable [[PTR_INT]] Function
// CHECK: %product = OpVariable [[PTR_FLOAT]] Function

// CHECK: OpStore %a [[INT_1]]
// CHECK: OpStore %b [[FLOAT_2]]
// CHECK: OpStore %c [[TRUE]]
// CHECK: OpStore %d [[VEC_CONST]]

RWBuffer<float> output : register(u0);

[numthreads(1,1,1)]
void main() {
// Auto deduces int from integer literal
auto a = 1;
// Auto deduces float from float literal
auto b = 2.0f;
// Auto deduces bool from bool literal
auto c = true;
// Auto deduces float4 from vector type
auto d = float4(1.0f, 2.0f, 3.0f, 4.0f);

// Auto from arithmetic expressions
auto sum = a + a;
auto product = b * b;

// Use the values to prevent dead-code elimination
output[0] = (float)sum + product + d.x + (float)c;
}
53 changes: 53 additions & 0 deletions tools/clang/test/CodeGenSPIRV/var.auto.template.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s -spirv | FileCheck %s

// Test that the 'auto' keyword works correctly in template contexts when
// targeting SPIR-V:
// - auto variables inside template function bodies
// - auto variables assigned from results of template function instantiations

RWBuffer<float> output : register(u0);

// Template with explicit return type; auto is used inside the body.
template<typename T>
T square(T val) {
auto result = val * val;
return result;
}

// Template with explicit return type using a conditional expression.
template<typename T>
T clampPositive(T val) {
auto zero = (T)0;
auto clamped = val < zero ? zero : val;
return clamped;
}

// CHECK: [[INT:%[a-zA-Z0-9_]+]] = OpTypeInt 32 1
// CHECK: [[FLOAT:%[a-zA-Z0-9_]+]] = OpTypeFloat 32
// CHECK: [[PTR_INT:%_ptr_Function_int]] = OpTypePointer Function [[INT]]
// CHECK: [[PTR_FLOAT:%_ptr_Function_float]] = OpTypePointer Function [[FLOAT]]

// Auto-deduced locals in main() instantiated for int and float.
// CHECK: %a = OpVariable [[PTR_INT]] Function
// CHECK: %b = OpVariable [[PTR_FLOAT]] Function
// CHECK: %c = OpVariable [[PTR_INT]] Function
// CHECK: %d = OpVariable [[PTR_FLOAT]] Function

// Auto inside template bodies retains correct types after instantiation.
// CHECK: %result = OpVariable [[PTR_INT]] Function
// CHECK: %result_0 = OpVariable [[PTR_FLOAT]] Function
// CHECK: %zero = OpVariable [[PTR_INT]] Function
// CHECK: %clamped = OpVariable [[PTR_INT]] Function
// CHECK: %zero_0 = OpVariable [[PTR_FLOAT]] Function
// CHECK: %clamped_0 = OpVariable [[PTR_FLOAT]] Function

[numthreads(1,1,1)]
void main() {
// auto variables assigned from template instantiation results.
auto a = square(5); // instantiated as int
auto b = square(2.5f); // instantiated as float
auto c = clampPositive(-3); // instantiated as int
auto d = clampPositive(1.5f); // instantiated as float

output[0] = (float)a + b + (float)c + d;
}
5 changes: 3 additions & 2 deletions tools/clang/test/HLSL/cpp-errors.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 };
int g_int;
typeof(g_int) g_typeof_int; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}} expected-error {{unknown type name 'typeof'; did you mean 'typedef'?}}
typedef int (*fn_int)(int); // expected-error {{pointers are unsupported in HLSL}}
auto g_auto = 3; // expected-error {{'auto' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
auto g_auto = 3; // auto is now supported in HLSL via type deduction; no error expected
__is_signed g_is_signed; // expected-error {{'__is_signed' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
register int g_register; // expected-error {{'register' is a reserved keyword in HLSL}}
__thread int g_thread; // expected-error {{'__thread' is a reserved keyword in HLSL}}
Expand Down Expand Up @@ -65,7 +65,8 @@ void fn_throw() throw() { } // expected-error {{exception specification is unsup
void fn_noexcept() noexcept { }; // expected-error {{expected function body after function declarator}}

// This would be a failure because of unsupported trailer return types, but we mis-parse it differently.
auto fn_trailing() -> int { return 1; } ; // expected-error {{'auto' is a reserved keyword in HLSL}} expected-error {{expected function body after function declarator}}
// auto is now type-deduced so no reserved keyword error; only the trailing return type syntax causes an error.
auto fn_trailing() -> int { return 1; } ; // expected-error {{expected function body after function declarator}}

void fn_param_with_default(int val = 1) { }
void fn_with_variadic(int a, ...) { } // expected-error {{variadic arguments is unsupported in HLSL}}
Expand Down
10 changes: 10 additions & 0 deletions tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-pointer.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %dxc -T cs_6_0 -HV 202x -verify %s

// Test that 'auto' cannot be used to declare pointer types in HLSL.
// Pointers are unsupported in HLSL.

[numthreads(1,1,1)]
void main() {
int x = 1;
auto* ptr = &x; // expected-error {{pointers are unsupported in HLSL}}
}
11 changes: 11 additions & 0 deletions tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-reference.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %dxc -T cs_6_0 -HV 202x -verify %s

// Test that 'auto' cannot be used to declare reference types in HLSL.
// References are unsupported in HLSL.

int gVal = 42;

[numthreads(1,1,1)]
void main() {
auto& ref = gVal; // expected-error {{references are unsupported in HLSL}}
}
41 changes: 41 additions & 0 deletions tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-template.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %dxc -T cs_6_0 -HV 202x -fcgl %s | FileCheck %s

// Test that the 'auto' keyword works correctly in template contexts in HLSL:
// - auto variables inside template function bodies
// - auto variables assigned from results of template function instantiations



RWBuffer<float> output : register(u0);

// Template with explicit return type; auto is used inside the body.
template<typename T>
T square(T val) {
auto result = val * val;
return result;
}

// Template with explicit return type using a conditional expression.
template<typename T>
T clampPositive(T val) {
auto zero = (T)0;
auto clamped = val < zero ? zero : val;
return clamped;
}

// CHECK-LABEL: define void @main()
// CHECK: {{.*}} = alloca i32
// CHECK: {{.*}} = alloca float
// CHECK: {{.*}} = alloca i32
// CHECK: {{.*}} = alloca float

[numthreads(1,1,1)]
void main() {
// auto variables assigned from template instantiation results.
auto a = square(5); // instantiated as int
auto b = square(2.5f); // instantiated as float
auto c = clampPositive(-3); // instantiated as int, result = 0
auto d = clampPositive(1.5f); // instantiated as float

output[0] = (float)a + b + (float)c + d;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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 to declare variables with inferred
// types from initialization expressions in HLSL.

// CHECK-LABEL: define void @main()
// CHECK: [[A:%[a-zA-Z0-9_]+]] = alloca i32
// CHECK: [[B:%[a-zA-Z0-9_]+]] = alloca float
// CHECK: [[C:%[a-zA-Z0-9_]+]] = alloca i32
// CHECK: [[D:%[a-zA-Z0-9_]+]] = alloca <4 x float>
// CHECK: {{.*}} = alloca i32
// CHECK: {{.*}} = alloca float
// CHECK: {{.*}} = alloca <4 x float>
// CHECK: {{.*}} = alloca i32
// CHECK: {{.*}} = alloca float
// CHECK: store i32 1, i32* [[A]]
// CHECK: store float 2.000000e+00, float* [[B]]
// CHECK: store i32 1, i32* [[C]]

RWBuffer<float> output : register(u0);

[numthreads(1,1,1)]
void main() {
// Auto deduces int from integer literal
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto a = 1;
// Auto deduces float from float literal
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto b = 2.0f;
// Auto deduces bool (stored as i32) from bool literal
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto c = true;
// Auto deduces float4 from vector type
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto d = float4(1.0f, 2.0f, 3.0f, 4.0f);

// Auto from arithmetic expressions
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto sum = a + a;
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto product = b * b;

Comment thread
hekota marked this conversation as resolved.
// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto mulAdd = mad(d, d, d);

// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto m = min(sum, c);

// expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}}
auto dP = dot(d, d);

// Use the values to prevent dead-code elimination
output[0] = (float)sum + product + d.x + (float)c;
}
Loading