Skip to content

Commit fb1f303

Browse files
authored
Error when declaring global operator overloads (microsoft#5796)
HLSL 2021 can't resolve calls to global operator overloads and was never intended to support them, but it didn't error on them being declared. This change emits a diagnostic when declaring any operator outside class or struct scope so that users won't instead be greeted by less intuitive errors from overload resolution. Fixes microsoft#5792
1 parent 99a8202 commit fb1f303

File tree

4 files changed

+122
-5
lines changed

4 files changed

+122
-5
lines changed

tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7499,8 +7499,8 @@ def err_hlsl_matrix_member_too_many_positions: Error<
74997499
"more than four positions are referenced in '%0'">;
75007500
def err_hlsl_matrix_member_zero_in_one_based: Error<
75017501
"the digit '0' is used in '%0', but the syntax is for one-based rows and columns">;
7502-
def err_hlsl_overloading_new_delete_operator: Error<
7503-
"overloading %0 is not allowed">;
7502+
def err_hlsl_overloading_operator_disallowed: Error<
7503+
"overloading %select{|non-member }1%0 is not allowed">;
75047504
def err_hlsl_vector_member_bad_format: Error<
75057505
"invalid format for vector swizzle '%0'">;
75067506
def err_hlsl_vector_member_empty: Error<

tools/clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11644,9 +11644,13 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
1164411644
Op == OO_PlusPlus || Op == OO_MinusMinus || Op == OO_ArrowStar ||
1164511645
Op == OO_Arrow) {
1164611646
return Diag(FnDecl->getLocation(),
11647-
diag::err_hlsl_overloading_new_delete_operator)
11648-
<< FnDecl->getDeclName();
11647+
diag::err_hlsl_overloading_operator_disallowed)
11648+
<< FnDecl->getDeclName() << 0;
1164911649
}
11650+
if (!isa<CXXMethodDecl>(FnDecl))
11651+
return Diag(FnDecl->getLocation(),
11652+
diag::err_hlsl_overloading_operator_disallowed)
11653+
<< FnDecl->getDeclName() << 1;
1165011654
}
1165111655
// HLSL Change Ends
1165211656

tools/clang/lib/Sema/SemaHLSL.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11175,7 +11175,9 @@ bool hlsl::ShouldSkipNRVO(clang::Sema &sema, clang::QualType returnType,
1117511175
// Check if it's an entry function the hard way
1117611176
if (!FD->getDeclContext()->isNamespace() && FD->isGlobal()) {
1117711177
// Check if this is an entry function by comparing name
11178-
if (FD->getName() == sema.getLangOpts().HLSLEntryFunction) {
11178+
// TODO: Remove this once we put HLSLShaderAttr on all entry functions.
11179+
if (FD->getIdentifier() &&
11180+
FD->getName() == sema.getLangOpts().HLSLEntryFunction) {
1117911181
return true;
1118011182
}
1118111183

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// RUN: %dxc -T lib_6_6 -HV 2021 %s -verify
2+
3+
// This test verifies that the set of operators that HLSL 2021 allows overriding
4+
// for correctly generates an error if the override is placed outside a class or
5+
// struct definition.
6+
7+
struct Test {};
8+
9+
Test operator*(float L, Test R) { // expected-error {{overloading non-member 'operator*' is not allowed}}
10+
return R;
11+
}
12+
13+
Test operator+(float L, Test R) { // expected-error {{overloading non-member 'operator+' is not allowed}}
14+
return R;
15+
}
16+
17+
Test operator-(float L, Test R) { // expected-error {{overloading non-member 'operator-' is not allowed}}
18+
return R;
19+
}
20+
21+
Test operator/(float L, Test R) { // expected-error {{overloading non-member 'operator/' is not allowed}}
22+
return R;
23+
}
24+
25+
Test operator%(float L, Test R) { // expected-error {{overloading non-member 'operator%' is not allowed}}
26+
return R;
27+
}
28+
29+
Test operator&(float L, Test R) { // expected-error {{overloading non-member 'operator&' is not allowed}}
30+
return R;
31+
}
32+
33+
Test operator|(float L, Test R) { // expected-error {{overloading non-member 'operator|' is not allowed}}
34+
return R;
35+
}
36+
37+
Test operator^(float L, Test R) { // expected-error {{overloading non-member 'operator^' is not allowed}}
38+
return R;
39+
}
40+
41+
Test operator<(float L, Test R) { // expected-error {{overloading non-member 'operator<' is not allowed}}
42+
return R;
43+
}
44+
45+
Test operator>(float L, Test R) { // expected-error {{overloading non-member 'operator>' is not allowed}}
46+
return R;
47+
}
48+
49+
Test operator<=(float L, Test R) { // expected-error {{overloading non-member 'operator<=' is not allowed}}
50+
return R;
51+
}
52+
53+
Test operator>=(float L, Test R) { // expected-error {{overloading non-member 'operator>=' is not allowed}}
54+
return R;
55+
}
56+
57+
Test operator==(float L, Test R) { // expected-error {{overloading non-member 'operator==' is not allowed}}
58+
return R;
59+
}
60+
61+
Test operator!=(float L, Test R) { // expected-error {{overloading non-member 'operator!=' is not allowed}}
62+
return R;
63+
}
64+
65+
namespace SomeNamespace {
66+
67+
Test operator*(float L, Test R) { // expected-error {{overloading non-member 'operator*' is not allowed}}
68+
return R;
69+
}
70+
71+
Test operator+(float L, Test R) { // expected-error {{overloading non-member 'operator+' is not allowed}}
72+
return R;
73+
}
74+
75+
Test operator-(float L, Test R) { // expected-error {{overloading non-member 'operator-' is not allowed}}
76+
return R;
77+
}
78+
79+
Test operator/(float L, Test R) { // expected-error {{overloading non-member 'operator/' is not allowed}}
80+
return R;
81+
}
82+
83+
Test operator%(float L, Test R) { // expected-error {{overloading non-member 'operator%' is not allowed}}
84+
return R;
85+
}
86+
87+
Test operator<(float L, Test R) { // expected-error {{overloading non-member 'operator<' is not allowed}}
88+
return R;
89+
}
90+
91+
Test operator>(float L, Test R) { // expected-error {{overloading non-member 'operator>' is not allowed}}
92+
return R;
93+
}
94+
95+
Test operator<=(float L, Test R) { // expected-error {{overloading non-member 'operator<=' is not allowed}}
96+
return R;
97+
}
98+
99+
Test operator>=(float L, Test R) { // expected-error {{overloading non-member 'operator>=' is not allowed}}
100+
return R;
101+
}
102+
103+
Test operator==(float L, Test R) { // expected-error {{overloading non-member 'operator==' is not allowed}}
104+
return R;
105+
}
106+
107+
Test operator!=(float L, Test R) { // expected-error {{overloading non-member 'operator!=' is not allowed}}
108+
return R;
109+
}
110+
111+
}

0 commit comments

Comments
 (0)