diff --git a/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/tools/clang/include/clang/Basic/DiagnosticParseKinds.td index 3de70da1e7..0fe0d22bbf 100644 --- a/tools/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1025,6 +1025,8 @@ def warn_hlsl_effect_technique : Warning < def warn_hlsl_semantic_identifier_collision : Warning < "'%0' interpreted as semantic; previous definition(s) ignored">, InGroup< HLSLSemanticIdentifierCollision >; +def err_hlsl_expected_hlsl_attribute : Error < + "Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?">; def err_hlsl_enum : Error< "enum is unsupported in HLSL before 2017">; def warn_hlsl_new_feature : Warning < diff --git a/tools/clang/lib/Parse/ParseDecl.cpp b/tools/clang/lib/Parse/ParseDecl.cpp index 59be41a484..d3f8d68443 100644 --- a/tools/clang/lib/Parse/ParseDecl.cpp +++ b/tools/clang/lib/Parse/ParseDecl.cpp @@ -633,6 +633,16 @@ bool Parser::MaybeParseHLSLAttributes(std::vector &ta Actions.DiagnoseSemanticDecl(pUA); ConsumeToken(); // consume semantic + // Likely a misspell of register(), packoffset() or a mismatching macro: + // both registr() and packofset() would cause a crash without this fix. + + if (Tok.is(tok::l_paren)) { + Diag(Tok.getLocation(), diag::err_hlsl_expected_hlsl_attribute); + ConsumeParen(); + SkipUntil(tok::r_paren, StopAtSemi); // skip through ) + return true; + } + target.push_back(pUA); } else { diff --git a/tools/clang/test/SemaHLSL/hlsl-attribute-mistype-errors.hlsl b/tools/clang/test/SemaHLSL/hlsl-attribute-mistype-errors.hlsl new file mode 100644 index 0000000000..edfbd95799 --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl-attribute-mistype-errors.hlsl @@ -0,0 +1,38 @@ +// RUN: %dxc -T lib_6_3 -verify %s + +// expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} +RWStructuredBuffer uav1 : registers(u3); + +// expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} +RWStructuredBuffer uav2 : registers(outer_space); + +// expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} +RWStructuredBuffer uav3 : UNDEFINED_MACRO1(u3); + +// expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} +RWStructuredBuffer uav4 : UNDEFINED_MACRO(something, more, complex); + +cbuffer buf { + + // expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} + float4 v0 : packoffsets(c0); + + // expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} + float4 v1 : packoffsets(invalid_syntax); + + // expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} + float v2 : UNDEFINED_MACRO2(c0.w); + + // expected-error@+1 {{Unexpected '(' in semantic annotation. Did you mean 'packoffset()' or 'register()'?}} + float v3 : UNDEFINED_MACRO(something, more, complex); +}; + +[shader("pixel")] +float4 main(): SV_Target +{ + uav1[0] = v0; + uav2[0] = v1; + uav3[0] = v2; + uav4[0] = v3; + return 0.xxxx; +}