[OpenCL] Allow addr space spelling without __ prefix in C++.
authorAnastasia Stulova <anastasia.stulova@arm.com>
Mon, 25 Mar 2019 11:54:02 +0000 (11:54 +0000)
committerAnastasia Stulova <anastasia.stulova@arm.com>
Mon, 25 Mar 2019 11:54:02 +0000 (11:54 +0000)
For backwards compatibility we allow alternative spelling of address
spaces - 'private', 'local', 'global', 'constant', 'generic'.

In order to accept 'private' correctly, parsing has been changed to
understand different use cases - access specifier vs address space.

Fixes PR40707 and PR41011!

Differential Revision: https://reviews.llvm.org/D59603

llvm-svn: 356888

clang/include/clang/Basic/TokenKinds.def
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseTentative.cpp
clang/test/Parser/opencl-cxx-keywords.cl

index ee0a782..0aeda6f 100644 (file)
@@ -539,11 +539,11 @@ KEYWORD(__local                     , KEYOPENCLC | KEYOPENCLCXX)
 KEYWORD(__constant                  , KEYOPENCLC | KEYOPENCLCXX)
 KEYWORD(__private                   , KEYOPENCLC | KEYOPENCLCXX)
 KEYWORD(__generic                   , KEYOPENCLC | KEYOPENCLCXX)
-ALIAS("global", __global            , KEYOPENCLC)
-ALIAS("local", __local              , KEYOPENCLC)
-ALIAS("constant", __constant        , KEYOPENCLC)
+ALIAS("global", __global            , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("local", __local              , KEYOPENCLC | KEYOPENCLCXX)
+ALIAS("constant", __constant        , KEYOPENCLC | KEYOPENCLCXX)
 ALIAS("private", __private          , KEYOPENCLC)
-ALIAS("generic", __generic          , KEYOPENCLC)
+ALIAS("generic", __generic          , KEYOPENCLC | KEYOPENCLCXX)
 // OpenCL function qualifiers
 KEYWORD(__kernel                    , KEYOPENCLC | KEYOPENCLCXX)
 ALIAS("kernel", __kernel            , KEYOPENCLC | KEYOPENCLCXX)
index c56c3c5..556fce2 100644 (file)
@@ -3824,6 +3824,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
         break;
       };
       LLVM_FALLTHROUGH;
+    case tok::kw_private:
     case tok::kw___private:
     case tok::kw___global:
     case tok::kw___local:
@@ -4790,6 +4791,7 @@ bool Parser::isTypeSpecifierQualifier() {
 
   case tok::kw___kindof:
 
+  case tok::kw_private:
   case tok::kw___private:
   case tok::kw___local:
   case tok::kw___global:
@@ -4980,6 +4982,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
 
   case tok::kw___kindof:
 
+  case tok::kw_private:
   case tok::kw___private:
   case tok::kw___local:
   case tok::kw___global:
@@ -5192,6 +5195,7 @@ void Parser::ParseTypeQualifierListOpt(
       break;
 
     // OpenCL qualifiers:
+    case tok::kw_private:
     case tok::kw___private:
     case tok::kw___global:
     case tok::kw___local:
index 895aa02..fe9fa10 100644 (file)
@@ -3047,9 +3047,14 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
     DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
     return nullptr;
 
+  case tok::kw_private:
+    // FIXME: We don't accept GNU attributes on access specifiers in OpenCL mode
+    // yet.
+    if (getLangOpts().OpenCL && !NextToken().is(tok::colon))
+      return ParseCXXClassMemberDeclaration(AS, AccessAttrs);
+    LLVM_FALLTHROUGH;
   case tok::kw_public:
-  case tok::kw_protected:
-  case tok::kw_private: {
+  case tok::kw_protected: {
     AccessSpecifier NewAS = getAccessSpecifierIfPresent();
     assert(NewAS != AS_none);
     // Current token is a C++ access specifier.
index 11f1aeb..81079cd 100644 (file)
@@ -1411,6 +1411,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
   case tok::kw_const:
   case tok::kw_volatile:
     // OpenCL address space qualifiers
+  case tok::kw_private:
   case tok::kw___private:
   case tok::kw___local:
   case tok::kw___global:
index 791da93..beae6f4 100644 (file)
@@ -19,32 +19,34 @@ kernel void test_exceptions() {
 // Test that only __-prefixed address space qualifiers are accepted.
 struct test_address_space_qualifiers {
   global int *g;
-  // expected-error@-1 {{unknown type name 'global'}}
-  // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
   __global int *uug;
-  int global; // should be fine in OpenCL C++
+  int global; // expected-warning{{declaration does not declare anything}}
 
   local int *l;
-  // expected-error@-1 {{unknown type name 'local'}}
-  // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
   __local int *uul;
-  int local; // should be fine in OpenCL C++
+  int local; // expected-warning{{declaration does not declare anything}}
 
   private int *p;
-  // expected-error@-1 {{expected ':'}}
   __private int *uup;
-  int private; // 'private' is a keyword in C++14 and thus in OpenCL C++
-  // expected-error@-1 {{expected member name or ';' after declaration specifiers}}
+  int private; // expected-warning{{declaration does not declare anything}}
 
   constant int *c;
-  // expected-error@-1 {{unknown type name 'constant'}}
-  // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
   __constant int *uuc;
-  int constant; // should be fine in OpenCL C++
+  int constant; // expected-warning{{declaration does not declare anything}}
 
   generic int *ge;
-  // expected-error@-1 {{unknown type name 'generic'}}
-  // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
   __generic int *uuge;
-  int generic; // should be fine in OpenCL C++
+  int generic; // expected-warning{{declaration does not declare anything}}
 };
+
+// Test that 'private' can be parsed as an access qualifier and an address space too.
+class A{
+  private:
+  private int i; //expected-error{{field may not be qualified with an address space}}
+};
+
+private ::A i; //expected-error{{program scope variable must reside in global or constant address space}}
+
+void foo(private int i);
+
+private int bar(); //expected-error{{return value cannot be qualified with address space}}