Skip to content

Commit ab214d2

Browse files
authored
[202x] Support >> without spaces (#8453)
This allows HLSL templates to have double closing angle brackets without a space between them matching C++11 template parsing.
1 parent 654d66f commit ab214d2

4 files changed

Lines changed: 88 additions & 8 deletions

File tree

tools/clang/lib/Parse/ParseExpr.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,11 @@ static bool isFoldOperator(tok::TokenKind Kind) {
254254
/// precedence of at least \p MinPrec.
255255
ExprResult
256256
Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
257-
prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),
258-
GreaterThanIsOperator,
259-
getLangOpts().CPlusPlus11);
257+
prec::Level NextTokPrec =
258+
getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
259+
getLangOpts().CPlusPlus11 ||
260+
(getLangOpts().HLSL && getLangOpts().HLSLVersion >=
261+
hlsl::LangStd::v202x));
260262
SourceLocation ColonLoc;
261263

262264
while (1) {
@@ -390,8 +392,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
390392
// Remember the precedence of this operator and get the precedence of the
391393
// operator immediately to the right of the RHS.
392394
prec::Level ThisPrec = NextTokPrec;
393-
NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
394-
getLangOpts().CPlusPlus11);
395+
NextTokPrec = getBinOpPrecedence(
396+
Tok.getKind(), GreaterThanIsOperator,
397+
getLangOpts().CPlusPlus11 ||
398+
(getLangOpts().HLSL &&
399+
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x));
395400

396401
// Assignment and conditional expressions are right-associative.
397402
bool isRightAssoc = ThisPrec == prec::Conditional ||
@@ -424,8 +429,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
424429
LHS = ExprError();
425430
}
426431

427-
NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
428-
getLangOpts().CPlusPlus11);
432+
NextTokPrec = getBinOpPrecedence(
433+
Tok.getKind(), GreaterThanIsOperator,
434+
getLangOpts().CPlusPlus11 ||
435+
(getLangOpts().HLSL &&
436+
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x));
429437
}
430438

431439
if (!RHS.isInvalid() && RHSIsInitList) {

tools/clang/lib/Parse/ParseTemplate.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
840840
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
841841

842842
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
843-
if (getLangOpts().CPlusPlus11 &&
843+
if ((getLangOpts().CPlusPlus11 ||
844+
(getLangOpts().HLSL &&
845+
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) &&
844846
(Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))
845847
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
846848
else if (Tok.is(tok::greaterequal))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s
2+
3+
// In HLSL 2021, two consecutive right angle brackets (>>) in a template
4+
// argument list must be separated by a space. Using >> without spaces should
5+
// produce an error.
6+
7+
template<typename T>
8+
struct Outer { T val; };
9+
10+
template<typename T>
11+
struct Inner { T val; };
12+
13+
// Nested template type using >> without space: should be an error in HLSL 2021.
14+
Outer<Inner<float>> g_nested; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}}
15+
16+
template<typename T>
17+
struct Wrapper {
18+
Outer<Inner<T>> field; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}}
19+
};
20+
21+
// Function return type with nested template and >>.
22+
Outer<Inner<int>> getVal(); // expected-error {{a space is required between consecutive right angle brackets (use '> >')}}
23+
24+
// Function parameter with nested template and >>.
25+
void takeVal(Outer<Inner<int>> v); // expected-error {{a space is required between consecutive right angle brackets (use '> >')}}
26+
27+
// Three right angle brackets (>>>) in a template should also error.
28+
template<typename T, typename U>
29+
struct Pair { T first; U second; };
30+
31+
Outer<Pair<float, Inner<int>>> g_triple; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %dxc -T lib_6_3 -HV 202x -verify %s
2+
// RUN: %dxc -T lib_6_3 -HV 202x -ast-dump %s 2>&1 | FileCheck %s
3+
4+
// In HLSL 202x, two consecutive right angle brackets (>>) are allowed in
5+
// template argument lists without spaces, matching C++11 behavior. No
6+
// diagnostic should be emitted for >> or >>> in this mode.
7+
8+
// expected-no-diagnostics
9+
10+
template<typename T>
11+
struct Outer { T val; };
12+
13+
template<typename T>
14+
struct Inner { T val; };
15+
16+
// Nested template type using >> without space: no error in HLSL 202x.
17+
// CHECK: VarDecl {{.*}} g_nested 'Outer<Inner<float> >'
18+
Outer<Inner<float>> g_nested;
19+
20+
template<typename T>
21+
struct Wrapper {
22+
// CHECK: FieldDecl {{.*}} field 'Outer<Inner<T> >'
23+
Outer<Inner<T>> field;
24+
};
25+
26+
// Function return type with nested template using >>.
27+
// CHECK: FunctionDecl {{.*}} getVal 'Outer<Inner<int> > ()'
28+
Outer<Inner<int>> getVal();
29+
30+
// Function parameter using >>.
31+
// CHECK: FunctionDecl {{.*}} takeVal 'void (Outer<Inner<int> >)'
32+
void takeVal(Outer<Inner<int>> v);
33+
34+
// Three right angle brackets (>>>) in a template: no error in HLSL 202x.
35+
template<typename T, typename U>
36+
struct Pair { T first; U second; };
37+
38+
// CHECK: VarDecl {{.*}} g_triple 'Outer<Pair<float, Inner<int> > >'
39+
Outer<Pair<float, Inner<int>>> g_triple;

0 commit comments

Comments
 (0)