From af6d489a6018c2372f4e3b425db5e57d1a15e274 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Fri, 15 May 2026 16:07:06 -0500 Subject: [PATCH] [202x] Support >> without spaces This allows HLSL templates to have double closing angle brackets without a space between them matching C++11 template parsing. ../tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-bracke ts.hlsl ../tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-bracke ts.hlsl --- tools/clang/lib/Parse/ParseExpr.cpp | 22 +++++++---- tools/clang/lib/Parse/ParseTemplate.cpp | 4 +- .../template-right-angle-brackets.hlsl | 31 +++++++++++++++ .../template-right-angle-brackets.hlsl | 39 +++++++++++++++++++ 4 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl create mode 100644 tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl diff --git a/tools/clang/lib/Parse/ParseExpr.cpp b/tools/clang/lib/Parse/ParseExpr.cpp index 8f51dd4b6c..9af3dbe610 100644 --- a/tools/clang/lib/Parse/ParseExpr.cpp +++ b/tools/clang/lib/Parse/ParseExpr.cpp @@ -254,9 +254,11 @@ static bool isFoldOperator(tok::TokenKind Kind) { /// precedence of at least \p MinPrec. ExprResult Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { - prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(), - GreaterThanIsOperator, - getLangOpts().CPlusPlus11); + prec::Level NextTokPrec = + getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, + getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && getLangOpts().HLSLVersion >= + hlsl::LangStd::v202x)); SourceLocation ColonLoc; while (1) { @@ -390,8 +392,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. prec::Level ThisPrec = NextTokPrec; - NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus11); + NextTokPrec = getBinOpPrecedence( + Tok.getKind(), GreaterThanIsOperator, + getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && + getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)); // Assignment and conditional expressions are right-associative. bool isRightAssoc = ThisPrec == prec::Conditional || @@ -424,8 +429,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { LHS = ExprError(); } - NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus11); + NextTokPrec = getBinOpPrecedence( + Tok.getKind(), GreaterThanIsOperator, + getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && + getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)); } if (!RHS.isInvalid() && RHSIsInitList) { diff --git a/tools/clang/lib/Parse/ParseTemplate.cpp b/tools/clang/lib/Parse/ParseTemplate.cpp index dc334cf7d6..fbedf41caa 100644 --- a/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/tools/clang/lib/Parse/ParseTemplate.cpp @@ -840,7 +840,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; - if (getLangOpts().CPlusPlus11 && + if ((getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && + getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) && (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater))) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) diff --git a/tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl b/tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl new file mode 100644 index 0000000000..4db25fabc0 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl @@ -0,0 +1,31 @@ +// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s + +// In HLSL 2021, two consecutive right angle brackets (>>) in a template +// argument list must be separated by a space. Using >> without spaces should +// produce an error. + +template +struct Outer { T val; }; + +template +struct Inner { T val; }; + +// Nested template type using >> without space: should be an error in HLSL 2021. +Outer> g_nested; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} + +template +struct Wrapper { + Outer> field; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} +}; + +// Function return type with nested template and >>. +Outer> getVal(); // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} + +// Function parameter with nested template and >>. +void takeVal(Outer> v); // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} + +// Three right angle brackets (>>>) in a template should also error. +template +struct Pair { T first; U second; }; + +Outer>> g_triple; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} diff --git a/tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl b/tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl new file mode 100644 index 0000000000..10790e9433 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl @@ -0,0 +1,39 @@ +// RUN: %dxc -T lib_6_3 -HV 202x -verify %s +// RUN: %dxc -T lib_6_3 -HV 202x -ast-dump %s 2>&1 | FileCheck %s + +// In HLSL 202x, two consecutive right angle brackets (>>) are allowed in +// template argument lists without spaces, matching C++11 behavior. No +// diagnostic should be emitted for >> or >>> in this mode. + +// expected-no-diagnostics + +template +struct Outer { T val; }; + +template +struct Inner { T val; }; + +// Nested template type using >> without space: no error in HLSL 202x. +// CHECK: VarDecl {{.*}} g_nested 'Outer >' +Outer> g_nested; + +template +struct Wrapper { + // CHECK: FieldDecl {{.*}} field 'Outer >' + Outer> field; +}; + +// Function return type with nested template using >>. +// CHECK: FunctionDecl {{.*}} getVal 'Outer > ()' +Outer> getVal(); + +// Function parameter using >>. +// CHECK: FunctionDecl {{.*}} takeVal 'void (Outer >)' +void takeVal(Outer> v); + +// Three right angle brackets (>>>) in a template: no error in HLSL 202x. +template +struct Pair { T first; U second; }; + +// CHECK: VarDecl {{.*}} g_triple 'Outer > >' +Outer>> g_triple;