Skip to content

Commit 0d6b574

Browse files
committed
[HLSL] Adjust access specifier behavior
HLSL doesn't support access specifiers. This change has two components: 1) Make default access for classes public 2) Diagnose the use of access specifiers as a clang HLSL extension As long as the default behavior for access specifiers matches HLSL, allowing them to be used doesn't cause sourece incompatability with valid code. As such enabling them as a clang extension seems like a reasonable approach. Fixes llvm#55124 Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D124487
1 parent bd30d4b commit 0d6b574

File tree

5 files changed

+74
-2
lines changed

5 files changed

+74
-2
lines changed

clang/include/clang/Basic/DiagnosticGroups.td

+3
Original file line numberDiff line numberDiff line change
@@ -1362,3 +1362,6 @@ def PedanticMacros : DiagGroup<"pedantic-macros",
13621362

13631363
def BranchProtection : DiagGroup<"branch-protection">;
13641364

1365+
// HLSL diagnostic groups
1366+
// Warnings for HLSL Clang extensions
1367+
def HLSLExtension : DiagGroup<"hlsl-extensions">;

clang/include/clang/Basic/DiagnosticParseKinds.td

+3
Original file line numberDiff line numberDiff line change
@@ -1599,5 +1599,8 @@ def note_max_tokens_total_override : Note<"total token limit set here">;
15991599
def err_expected_semantic_identifier : Error<
16001600
"expected HLSL Semantic identifier">;
16011601
def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">;
1602+
def ext_hlsl_access_specifiers : ExtWarn<
1603+
"access specifiers are a clang HLSL extension">,
1604+
InGroup<HLSLExtension>;
16021605

16031606
} // end of Parser diagnostics

clang/lib/Parse/ParseDeclCXX.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -2170,8 +2170,11 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
21702170

21712171
// Parse an (optional) access specifier.
21722172
AccessSpecifier Access = getAccessSpecifierIfPresent();
2173-
if (Access != AS_none)
2173+
if (Access != AS_none) {
21742174
ConsumeToken();
2175+
if (getLangOpts().HLSL)
2176+
Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);
2177+
}
21752178

21762179
CheckMisplacedCXX11Attribute(Attributes, StartLoc);
21772180

@@ -3270,6 +3273,8 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
32703273
LLVM_FALLTHROUGH;
32713274
case tok::kw_public:
32723275
case tok::kw_protected: {
3276+
if (getLangOpts().HLSL)
3277+
Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);
32733278
AccessSpecifier NewAS = getAccessSpecifierIfPresent();
32743279
assert(NewAS != AS_none);
32753280
// Current token is a C++ access specifier.
@@ -3509,8 +3514,9 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
35093514
// C++ 11p3: Members of a class defined with the keyword class are private
35103515
// by default. Members of a class defined with the keywords struct or union
35113516
// are public by default.
3517+
// HLSL: In HLSL members of a class are public by default.
35123518
AccessSpecifier CurAS;
3513-
if (TagType == DeclSpec::TST_class)
3519+
if (TagType == DeclSpec::TST_class && !getLangOpts().HLSL)
35143520
CurAS = AS_private;
35153521
else
35163522
CurAS = AS_public;

clang/lib/Sema/SemaDeclCXX.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,11 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
25012501
bool Virtual, AccessSpecifier Access,
25022502
TypeSourceInfo *TInfo,
25032503
SourceLocation EllipsisLoc) {
2504+
// In HLSL, unspecified class access is public rather than private.
2505+
if (getLangOpts().HLSL && Class->getTagKind() == TTK_Class &&
2506+
Access == AS_none)
2507+
Access = AS_public;
2508+
25042509
QualType BaseType = TInfo->getType();
25052510
if (BaseType->containsErrors()) {
25062511
// Already emitted a diagnostic when parsing the error type.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s -verify
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -DSTRUCT -o - %s -verify
3+
4+
#ifdef STRUCT
5+
#define KEYWORD struct
6+
#else
7+
#define KEYWORD class
8+
#endif
9+
10+
KEYWORD Doggo {
11+
int legs; // expected-note {{member is declared here}} expected-note {{member is declared here}}
12+
protected: // expected-warning {{access specifiers are a clang HLSL extension}}
13+
int ears[2]; // expected-note {{declared protected here}}
14+
private: // expected-warning {{access specifiers are a clang HLSL extension}}
15+
int tail; // expected-note {{declared private here}} expected-note {{declared private here}}
16+
};
17+
18+
KEYWORD Shiba : public Doggo { // expected-warning {{access specifiers are a clang HLSL extension}}
19+
int undercoat;
20+
};
21+
22+
KEYWORD Akita : Doggo {
23+
int floof;
24+
};
25+
26+
KEYWORD Chow : private Doggo { // expected-warning {{access specifiers are a clang HLSL extension}} expected-note {{constrained by private inheritance here}}
27+
int megafloof;
28+
};
29+
30+
KEYWORD Dachshund : protected Doggo { // expected-warning {{access specifiers are a clang HLSL extension}} expected-note {{constrained by protected inheritance here}}
31+
int wiry;
32+
};
33+
34+
void Puppers() {
35+
Shiba Shibe;
36+
Shibe.undercoat = 0xFFFF;
37+
Shibe.legs = 4;
38+
39+
Shibe.tail = 1; // expected-error {{'tail' is a private member of 'Doggo'}}
40+
Shibe.ears[0] = 1; // expected-error {{'ears' is a protected member of 'Doggo'}}
41+
42+
Akita Aki;
43+
Aki.floof = 0xFFFF;
44+
Aki.legs = 4;
45+
46+
Aki.tail = 1; // expected-error {{'tail' is a private member of 'Doggo'}}
47+
48+
Chow Ch;
49+
Ch.megafloof = 0xFFFF;
50+
51+
Ch.legs = 4; // expected-error {{'legs' is a private member of 'Doggo'}}
52+
53+
Dachshund DH;
54+
DH.legs = 4; // expected-error {{'legs' is a protected member of 'Doggo'}}
55+
}

0 commit comments

Comments
 (0)