From 948e37c8ca8b4a4b72b0745c643fee1e4482c2d0 Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Mon, 25 Mar 2019 11:54:02 +0000 Subject: [PATCH] [OpenCL] Allow addr space spelling without __ prefix in C++. 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 | 8 ++++---- clang/lib/Parse/ParseDecl.cpp | 4 ++++ clang/lib/Parse/ParseDeclCXX.cpp | 9 +++++++-- clang/lib/Parse/ParseTentative.cpp | 1 + clang/test/Parser/opencl-cxx-keywords.cl | 32 +++++++++++++++++--------------- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index ee0a782..0aeda6f 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -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) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c56c3c5..556fce2 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -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: diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 895aa02..fe9fa10 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3047,9 +3047,14 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( DiagnoseUnexpectedNamespace(cast(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. diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 11f1aeb..81079cd 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -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: diff --git a/clang/test/Parser/opencl-cxx-keywords.cl b/clang/test/Parser/opencl-cxx-keywords.cl index 791da93..beae6f4 100644 --- a/clang/test/Parser/opencl-cxx-keywords.cl +++ b/clang/test/Parser/opencl-cxx-keywords.cl @@ -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}} -- 2.7.4