beanz created this revision.
beanz added reviewers: aaron.ballman, MaskRay, kuhar, rsmith.
Herald added subscribers: Anastasia, StephenFan.
Herald added a project: All.
beanz requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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 #55124


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124487

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/ParserHLSL/access_specifiers.hlsl

Index: clang/test/ParserHLSL/access_specifiers.hlsl
===================================================================
--- /dev/null
+++ clang/test/ParserHLSL/access_specifiers.hlsl
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s -verify
+
+class Doggo {
+  // expected-note@+1 {{member is declared here}}
+  int legs;
+// expected-warning@+1 {{access specifiers are a clang HLSL extension}}
+private:
+  // expected-note@+2 {{declared private here}}
+  // expected-note@+1 {{declared private here}}
+  int tail;
+};
+
+// expected-warning@+1 {{access specifiers are a clang HLSL extension}}
+class Shiba : public Doggo {
+  int undercoat;
+};
+
+class Akita : Doggo {
+  int floof;
+};
+
+// expected-note@+2 {{constrained by private inheritance here}}
+// expected-warning@+1 {{access specifiers are a clang HLSL extension}}
+class Chow : private Doggo {
+  int megafloof;
+};
+
+void main() {
+  Shiba Shibe;
+  Shibe.undercoat = 0xFFFF;
+  Shibe.legs = 4;
+
+  // expected-error@+1 {{'tail' is a private member of 'Doggo'}}
+  Shibe.tail = 1;
+
+  Akita Aki;
+  Aki.floof = 0xFFFF;
+  Aki.legs = 4;
+
+  // expected-error@+1 {{'tail' is a private member of 'Doggo'}}
+  Aki.tail = 1;
+
+  Chow Ch;
+  Ch.megafloof = 0xFFFF;
+
+  // expected-error@+1 {{'legs' is a private member of 'Doggo'}}
+  Ch.legs = 4;
+}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -2501,6 +2501,11 @@
                          bool Virtual, AccessSpecifier Access,
                          TypeSourceInfo *TInfo,
                          SourceLocation EllipsisLoc) {
+  // In HLSL, unspecified class access is public rather than private.
+  if (getLangOpts().HLSL && Class->getTagKind() == TTK_Class &&
+      Access == AS_none)
+    Access = AS_public;
+
   QualType BaseType = TInfo->getType();
   if (BaseType->containsErrors()) {
     // Already emitted a diagnostic when parsing the error type.
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2170,8 +2170,11 @@
 
   // Parse an (optional) access specifier.
   AccessSpecifier Access = getAccessSpecifierIfPresent();
-  if (Access != AS_none)
+  if (Access != AS_none) {
     ConsumeToken();
+    if (getLangOpts().HLSL)
+      Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);
+  }
 
   CheckMisplacedCXX11Attribute(Attributes, StartLoc);
 
@@ -3270,6 +3273,8 @@
     LLVM_FALLTHROUGH;
   case tok::kw_public:
   case tok::kw_protected: {
+    if (getLangOpts().HLSL)
+      Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);
     AccessSpecifier NewAS = getAccessSpecifierIfPresent();
     assert(NewAS != AS_none);
     // Current token is a C++ access specifier.
@@ -3509,8 +3514,9 @@
   // C++ 11p3: Members of a class defined with the keyword class are private
   // by default. Members of a class defined with the keywords struct or union
   // are public by default.
+  // HLSL: In HLSL members of a class are public by default.
   AccessSpecifier CurAS;
-  if (TagType == DeclSpec::TST_class)
+  if (TagType == DeclSpec::TST_class && !getLangOpts().HLSL)
     CurAS = AS_private;
   else
     CurAS = AS_public;
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1599,5 +1599,7 @@
 def err_expected_semantic_identifier : Error<
   "expected HLSL Semantic identifier">;
 def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">;
+def ext_hlsl_access_specifiers : ExtWarn<
+  "access specifiers are a clang HLSL extension">;
 
 } // end of Parser diagnostics
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to