diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1362,3 +1362,6 @@ def BranchProtection : DiagGroup<"branch-protection">; +// HLSL diagnostic groups +// Warnings for HLSL Clang extensions +def HLSLExtension : DiagGroup<"hlsl-extensions">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1599,5 +1599,8 @@ 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">, + InGroup; } // end of Parser diagnostics diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/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; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/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. diff --git a/clang/test/ParserHLSL/access_specifiers.hlsl b/clang/test/ParserHLSL/access_specifiers.hlsl new file mode 100644 --- /dev/null +++ b/clang/test/ParserHLSL/access_specifiers.hlsl @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s -verify +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -DSTRUCT -o - %s -verify + +#ifdef STRUCT +#define KEYWORD struct +#else +#define KEYWORD class +#endif + +KEYWORD Doggo { + int legs; // expected-note {{member is declared here}} expected-note {{member is declared here}} +protected: // expected-warning {{access specifiers are a clang HLSL extension}} + int ears[2]; // expected-note {{declared protected here}} +private: // expected-warning {{access specifiers are a clang HLSL extension}} + int tail; // expected-note {{declared private here}} expected-note {{declared private here}} +}; + +KEYWORD Shiba : public Doggo { // expected-warning {{access specifiers are a clang HLSL extension}} + int undercoat; +}; + +KEYWORD Akita : Doggo { + int floof; +}; + +KEYWORD Chow : private Doggo { // expected-warning {{access specifiers are a clang HLSL extension}} expected-note {{constrained by private inheritance here}} + int megafloof; +}; + +KEYWORD Dachshund : protected Doggo { // expected-warning {{access specifiers are a clang HLSL extension}} expected-note {{constrained by protected inheritance here}} + int wiry; +}; + +void Puppers() { + Shiba Shibe; + Shibe.undercoat = 0xFFFF; + Shibe.legs = 4; + + Shibe.tail = 1; // expected-error {{'tail' is a private member of 'Doggo'}} + Shibe.ears[0] = 1; // expected-error {{'ears' is a protected member of 'Doggo'}} + + Akita Aki; + Aki.floof = 0xFFFF; + Aki.legs = 4; + + Aki.tail = 1; // expected-error {{'tail' is a private member of 'Doggo'}} + + Chow Ch; + Ch.megafloof = 0xFFFF; + + Ch.legs = 4; // expected-error {{'legs' is a private member of 'Doggo'}} + + Dachshund DH; + DH.legs = 4; // expected-error {{'legs' is a protected member of 'Doggo'}} +}