[OPENMP] Allow use of declare target directive inside struct
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 3 Oct 2017 20:00:00 +0000 (20:00 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 3 Oct 2017 20:00:00 +0000 (20:00 +0000)
declaration.

Patch allows using of the `#pragma omp declare target`| `#pragma omp end
declare target` directives inside the structures if we need to mark as
declare target only some static members.

llvm-svn: 314833

clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/test/OpenMP/declare_target_ast_print.cpp
clang/test/OpenMP/declare_target_messages.cpp

index 669e9aff8021c8a8389b031d912e31ec7ccab588..e1685f6a9dbfc467a81e22dad9375d26b1abe3f9 100644 (file)
@@ -760,9 +760,17 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
     DKind = ParseOpenMPDirectiveKind(*this);
     while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
            Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
-      ParsedAttributesWithRange attrs(AttrFactory);
-      MaybeParseCXX11Attributes(attrs);
-      ParseExternalDeclaration(attrs);
+      DeclGroupPtrTy Ptr;
+      // Here we expect to see some function declaration.
+      if (AS == AS_none) {
+        assert(TagType == DeclSpec::TST_unspecified);
+        MaybeParseCXX11Attributes(Attrs);
+        ParsingDeclSpec PDS(*this);
+        Ptr = ParseExternalDeclaration(Attrs, &PDS);
+      } else {
+        Ptr =
+            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
+      }
       if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
         TentativeParsingAction TPA(*this);
         ConsumeAnnotationToken();
index 8bded5854aa3b74ca781af23ebeee3ed532b4d8d..81fea56033c98c65b141d4cf00330aa29deead71 100644 (file)
@@ -11914,7 +11914,11 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
   DeclContext *CurLexicalContext = getCurLexicalContext();
   if (!CurLexicalContext->isFileContext() &&
       !CurLexicalContext->isExternCContext() &&
-      !CurLexicalContext->isExternCXXContext()) {
+      !CurLexicalContext->isExternCXXContext() &&
+      !isa<CXXRecordDecl>(CurLexicalContext) &&
+      !isa<ClassTemplateDecl>(CurLexicalContext) &&
+      !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
+      !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
     Diag(Loc, diag::err_omp_region_not_file_context);
     return false;
   }
index 591844b7949819941c55d2747ebb92b2cf27c5bf..55f73cbc4e97eb5a54708646e8135e7ca5d14443 100644 (file)
@@ -124,6 +124,33 @@ void f3() {
 // CHECK: void f3()
 // CHECK: #pragma omp end declare target
 
+struct SSSt {
+#pragma omp declare target
+  static int a;
+  int b;
+#pragma omp end declare target
+};
+
+// CHECK: struct SSSt {
+// CHECK: #pragma omp declare target
+// CHECK: static int a;
+// CHECK: #pragma omp end declare target
+// CHECK: int b;
+
+template <class T>
+struct SSSTt {
+#pragma omp declare target
+  static T a;
+  int b;
+#pragma omp end declare target
+};
+
+// CHECK: template <class T> struct SSSTt {
+// CHECK: #pragma omp declare target
+// CHECK: static T a;
+// CHECK: #pragma omp end declare target
+// CHECK: int b;
+
 int main (int argc, char **argv) {
   foo();
   foo_c();
index 5180dd762bdb2d4ffb01a6a6dd826470db71520b..bbffc0eeeb2a068425375f0e55d238fc12ae7f1a 100644 (file)
@@ -73,9 +73,9 @@ int C::method() {
 }
 
 struct S {
-#pragma omp declare target // expected-error {{directive must be at file or namespace scope}}
+#pragma omp declare target
   int v;
-#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
+#pragma omp end declare target
 };
 
 int main (int argc, char **argv) {