r264853 - [OPENMP 4.0] Initial support for '#pragma omp declare simd' directive.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 30 03:43:56 PDT 2016


Author: abataev
Date: Wed Mar 30 05:43:55 2016
New Revision: 264853

URL: http://llvm.org/viewvc/llvm-project?rev=264853&view=rev
Log:
[OPENMP 4.0] Initial support for '#pragma omp declare simd' directive.

Initial parsing/sema/serialization/deserialization support for '#pragma
omp declare simd' directive.
The 'declare simd' construct can be applied to a function to enable the
creation of one or more versions that can process multiple arguments
using SIMD instructions from a single invocation from a SIMD loop.
If the function has any declarations, then the declare simd construct
for any declaration that has one must be equivalent to the one specified
 for the definition. Otherwise, the result is unspecified.
This pragma can be applied many times to the same declaration.
Internally this pragma is represented as an attribute. But we need special processing for this pragma because it must be used before function declaration, this directive is applied to.
Differential Revision: http://reviews.llvm.org/D10599

Added:
    cfe/trunk/test/OpenMP/declare_simd_ast_print.c
    cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp
    cfe/trunk/test/OpenMP/declare_simd_messages.cpp
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/OpenMPKinds.def
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Basic/OpenMPKinds.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Mar 30 05:43:55 2016
@@ -2244,6 +2244,17 @@ def OMPCaptureNoInit : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def OMPDeclareSimdDecl : Attr {
+  let Spellings = [Pragma<"omp", "declare simd">];
+  let Subjects = SubjectList<[Function]>;
+  let SemaHandler = 0;
+  let HasCustomParsing = 1;
+  let Documentation = [OMPDeclareSimdDocs];
+  let AdditionalMembers = [{
+  void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {}
+  }];
+}
+
 def InternalLinkage : InheritableAttr {
   let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
   let Subjects = SubjectList<[Var, Function, CXXRecord]>;

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Mar 30 05:43:55 2016
@@ -1888,6 +1888,41 @@ arguments, with arbitrary offsets.
   }];
 }
 
+def OMPDeclareSimdDocs : Documentation {
+  let Category = DocCatStmt;
+  let Heading = "#pragma omp declare simd";
+  let Content = [{
+The `declare simd` construct can be applied to a function to enable the creation
+of one or more versions that can process multiple arguments using SIMD
+instructions from a single invocation in a SIMD loop. The `declare simd`
+directive is a declarative directive. There may be multiple `declare simd`
+directives for a function. The use of a `declare simd` construct on a function
+enables the creation of SIMD versions of the associated function that can be
+used to process multiple arguments from a single invocation from a SIMD loop
+concurrently.
+The syntax of the `declare simd` construct is as follows:
+
+  .. code-block:: c
+
+  #pragma omp declare simd [clause[[,] clause] ...] new-line
+  [#pragma omp declare simd [clause[[,] clause] ...] new-line]
+  [...]
+  function definition or declaration
+
+where clause is one of the following:
+
+  .. code-block:: c
+
+  simdlen(length)
+  linear(argument-list[:constant-linear-step])
+  aligned(argument-list[:alignment])
+  uniform(argument-list)
+  inbranch
+  notinbranch
+
+  }];
+}
+
 def NotTailCalledDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Mar 30 05:43:55 2016
@@ -953,6 +953,8 @@ def err_omp_expected_identifier_for_crit
   "expected identifier specifying the name of the 'omp critical' directive">;
 def err_omp_expected_reduction_identifier : Error<
   "expected identifier or one of the following operators: '+', '-', '*', '&', '|', '^', '&&', or '||'">;
+def err_omp_decl_in_declare_simd : Error<
+  "function declaration is expected after 'declare simd' directive">;
 def err_omp_unknown_map_type : Error<
   "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
 def err_omp_unknown_map_type_modifier : Error<

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 30 05:43:55 2016
@@ -8039,6 +8039,10 @@ def err_omp_single_copyprivate_with_nowa
   "the 'copyprivate' clause must not be used with the 'nowait' clause">;
 def note_omp_nowait_clause_here : Note<
   "'nowait' clause is here">;
+def err_omp_single_decl_in_declare_simd : Error<
+  "single declaration is expected after 'declare simd' directive">;
+def err_omp_function_expected : Error<
+  "'#pragma omp declare simd' can only be applied to functions">;
 def err_omp_wrong_cancel_region : Error<
   "one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
 def err_omp_parent_cancel_region_nowait : Error<

Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Wed Mar 30 05:43:55 2016
@@ -156,6 +156,7 @@ OPENMP_DIRECTIVE_EXT(parallel_sections,
 OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
 OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
 OPENMP_DIRECTIVE_EXT(declare_reduction, "declare reduction")
+OPENMP_DIRECTIVE_EXT(declare_simd, "declare simd")
 OPENMP_DIRECTIVE(taskloop)
 OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
 OPENMP_DIRECTIVE(distribute)

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Mar 30 05:43:55 2016
@@ -2428,7 +2428,7 @@ private:
       ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
   DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(
       AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
-      DeclSpec::TST TagType, Decl *TagDecl);
+      DeclSpec::TST TagType, Decl *Tag);
   void ParseConstructorInitializer(Decl *ConstructorDecl);
   MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
   void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
@@ -2457,7 +2457,10 @@ private:
   //===--------------------------------------------------------------------===//
   // OpenMP: Directives and clauses.
   /// \brief Parses declarative OpenMP directives.
-  DeclGroupPtrTy ParseOpenMPDeclarativeDirective(AccessSpecifier AS);
+  DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
+      AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
+      DeclSpec::TST TagType = DeclSpec::TST_unspecified,
+      Decl *TagDecl = nullptr);
   /// \brief Parse 'omp declare reduction' construct.
   DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
   /// \brief Parses simple list of variables.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 30 05:43:55 2016
@@ -146,6 +146,7 @@ namespace clang {
   class ObjCProtocolDecl;
   class OMPThreadPrivateDecl;
   class OMPDeclareReductionDecl;
+  class OMPDeclareSimdDecl;
   class OMPClause;
   struct OverloadCandidate;
   class OverloadCandidateSet;
@@ -8087,6 +8088,11 @@ public:
       SourceLocation EndLoc,
       llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
 
+  /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of
+  /// the associated method/function.
+  DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
+                                                 SourceLocation StartLoc);
+
   OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                          Expr *Expr,
                                          SourceLocation StartLoc,

Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Wed Mar 30 05:43:55 2016
@@ -485,6 +485,8 @@ bool clang::isAllowedClauseForDirective(
       break;
     }
     break;
+  case OMPD_declare_simd:
+    break;
   case OMPD_cancel:
     switch (CKind) {
 #define OPENMP_CANCEL_CLAUSE(Name)                                             \

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Mar 30 05:43:55 2016
@@ -3654,8 +3654,10 @@ void Parser::ParseStructUnionBody(Source
     }
 
     if (Tok.is(tok::annot_pragma_openmp)) {
-      // There may be declared reduction operator inside structure/union.
-      (void)ParseOpenMPDeclarativeDirective(AS_public);
+      // Result can be ignored, because it must be always empty.
+      AccessSpecifier AS = AS_none;
+      ParsedAttributesWithRange Attrs(AttrFactory);
+      (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
       continue;
     }
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Mar 30 05:43:55 2016
@@ -2919,7 +2919,8 @@ Parser::DeclGroupPtrTy Parser::ParseCXXC
   }
 
   if (Tok.is(tok::annot_pragma_openmp))
-    return ParseOpenMPDeclarativeDirective(AS);
+    return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType,
+                                                      TagDecl);
 
   // Parse all the comma separated declarators.
   return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Wed Mar 30 05:43:55 2016
@@ -65,6 +65,7 @@ static OpenMPDirectiveKind ParseOpenMPDi
   static const unsigned F[][3] = {
     { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
     { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
+    { OMPD_declare, OMPD_simd, OMPD_declare_simd },
     { OMPD_target, OMPD_data, OMPD_target_data },
     { OMPD_target, OMPD_enter, OMPD_target_enter },
     { OMPD_target, OMPD_exit, OMPD_target_exit },
@@ -332,8 +333,14 @@ Parser::ParseOpenMPDeclareReductionDirec
 ///        annot_pragma_openmp 'declare' 'reduction' [...]
 ///        annot_pragma_openmp_end
 ///
-Parser::DeclGroupPtrTy
-Parser::ParseOpenMPDeclarativeDirective(AccessSpecifier AS) {
+///       declare-simd-directive:
+///         annot_pragma_openmp 'declare simd' {<clause> [,]}
+///         annot_pragma_openmp_end
+///         <function declaration/definition>
+///
+Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
+    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
+    DeclSpec::TST TagType, Decl *Tag) {
   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
   ParenBraceBracketBalancer BalancerRAIIObj(*this);
 
@@ -373,6 +380,47 @@ Parser::ParseOpenMPDeclarativeDirective(
       return Res;
     }
     break;
+  case OMPD_declare_simd: {
+    // The syntax is:
+    // { #pragma omp declare simd }
+    // <function-declaration-or-definition>
+    //
+
+    ConsumeToken();
+    // The last seen token is annot_pragma_openmp_end - need to check for
+    // extra tokens.
+    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
+      Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
+          << getOpenMPDirectiveName(OMPD_declare_simd);
+      while (Tok.isNot(tok::annot_pragma_openmp_end))
+        ConsumeAnyToken();
+    }
+    // Skip the last annot_pragma_openmp_end.
+    ConsumeToken();
+
+    DeclGroupPtrTy Ptr;
+    if (Tok.is(tok::annot_pragma_openmp)) {
+      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
+    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+      // Here we expect to see some function declaration.
+      if (AS == AS_none) {
+        assert(TagType == DeclSpec::TST_unspecified);
+        MaybeParseCXX11Attributes(Attrs);
+        MaybeParseMicrosoftAttributes(Attrs);
+        ParsingDeclSpec PDS(*this);
+        Ptr = ParseExternalDeclaration(Attrs, &PDS);
+      } else {
+        Ptr =
+            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
+      }
+    }
+    if (!Ptr) {
+      Diag(Loc, diag::err_omp_decl_in_declare_simd);
+      return DeclGroupPtrTy();
+    }
+
+    return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, Loc);
+  }
   case OMPD_unknown:
     Diag(Tok, diag::err_omp_unknown_directive);
     break;
@@ -627,6 +675,11 @@ StmtResult Parser::ParseOpenMPDeclarativ
     OMPDirectiveScope.Exit();
     break;
   }
+  case OMPD_declare_simd:
+    Diag(Tok, diag::err_omp_unexpected_directive)
+        << getOpenMPDirectiveName(DKind);
+    SkipUntil(tok::annot_pragma_openmp_end);
+    break;
   case OMPD_unknown:
     Diag(Tok, diag::err_omp_unknown_directive);
     SkipUntil(tok::annot_pragma_openmp_end);

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Mar 30 05:43:55 2016
@@ -659,8 +659,10 @@ Parser::ParseExternalDeclaration(ParsedA
   case tok::annot_pragma_opencl_extension:
     HandlePragmaOpenCLExtension();
     return nullptr;
-  case tok::annot_pragma_openmp:
-    return ParseOpenMPDeclarativeDirective(/*AS=*/AS_none);
+  case tok::annot_pragma_openmp: {
+    AccessSpecifier AS = AS_none;
+    return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs);
+  }
   case tok::annot_pragma_ms_pointers_to_members:
     HandlePragmaMSPointersToMembers();
     return nullptr;

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=264853&r1=264852&r2=264853&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Mar 30 05:43:55 2016
@@ -1701,6 +1701,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMP
   case OMPD_target_enter_data:
   case OMPD_target_exit_data:
   case OMPD_declare_reduction:
+  case OMPD_declare_simd:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
     llvm_unreachable("Unknown OpenMP directive");
@@ -3155,6 +3156,7 @@ StmtResult Sema::ActOnOpenMPExecutableDi
     break;
   case OMPD_threadprivate:
   case OMPD_declare_reduction:
+  case OMPD_declare_simd:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
     llvm_unreachable("Unknown OpenMP directive");
@@ -3175,6 +3177,32 @@ StmtResult Sema::ActOnOpenMPExecutableDi
   return Res;
 }
 
+Sema::DeclGroupPtrTy
+Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
+                                      SourceLocation StartLoc) {
+  if (!DG || DG.get().isNull())
+    return DeclGroupPtrTy();
+
+  if (!DG.get().isSingleDecl()) {
+    Diag(StartLoc, diag::err_omp_single_decl_in_declare_simd);
+    return DG;
+  }
+  auto *ADecl = DG.get().getSingleDecl();
+  if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
+    ADecl = FTD->getTemplatedDecl();
+
+  if (!isa<FunctionDecl>(ADecl)) {
+    Diag(ADecl->getLocation(), diag::err_omp_function_expected)
+        << ADecl->getDeclContext()->isFileContext();
+    return DeclGroupPtrTy();
+  }
+
+  auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
+      Context, SourceRange(StartLoc, StartLoc));
+  ADecl->addAttr(NewAttr);
+  return ConvertDeclToDeclGroup(ADecl);
+}
+
 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
                                               Stmt *AStmt,
                                               SourceLocation StartLoc,

Added: cfe/trunk/test/OpenMP/declare_simd_ast_print.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_ast_print.c?rev=264853&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/declare_simd_ast_print.c (added)
+++ cfe/trunk/test/OpenMP/declare_simd_ast_print.c Wed Mar 30 05:43:55 2016
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+#pragma omp declare simd
+#pragma omp declare simd
+void add_1(float *d, float *s1, float *s2) __attribute__((cold));
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: #pragma omp declare simd
+// CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold))
+
+#endif

Added: cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp?rev=264853&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp (added)
+++ cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp Wed Mar 30 05:43:55 2016
@@ -0,0 +1,131 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+#pragma omp declare simd
+void add_1(float *d) __attribute__((cold));
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: void add_1(float *d) __attribute__((cold));
+//
+
+#pragma omp declare simd
+template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
+}
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: template <class C = int> void h(int *hp, int *hp2, int *hq, int *lin) {
+// CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
+// CHECK-NEXT: }
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: template <class C = float> void h(float *hp, float *hp2, float *hq, float *lin) {
+// CHECK-NEXT: }
+
+// CHECK: #pragma omp declare simd
+// CHECK: template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
+// CHECK-NEXT: }
+//
+
+// Explicit specialization with <C=int>.
+// Pragmas need to be same, otherwise standard says that's undefined behavior.
+#pragma omp declare simd
+template <>
+void h(int *hp, int *hp2, int *hq, int *lin)
+{
+  // Implicit specialization with <C=float>.
+  // This is special case where the directive is stored by Sema and is
+  // generated together with the (pending) function instatiation.
+  h((float*) hp, (float*) hp2, (float*) hq, (float*) lin);
+}
+
+class VV {
+  // CHECK: #pragma omp declare simd
+  // CHECK-NEXT: int add(int a, int b) __attribute__((cold))    {
+  // CHECK-NEXT: return a + b;
+  // CHECK-NEXT: }
+  #pragma omp declare simd
+  int add(int a, int b) __attribute__((cold)) { return a + b; }
+
+  // CHECK: #pragma omp declare simd
+  // CHECK-NEXT: float taddpf(float *a, float *b)     {
+  // CHECK-NEXT: return *a + *b;
+  // CHECK-NEXT: }
+  #pragma omp declare simd
+  float taddpf(float *a, float *b) { return *a + *b; }
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: #pragma omp declare simd
+// CHECK-NEXT: int tadd(int b) {
+// CHECK-NEXT: return this->x[b] + b;
+// CHECK-NEXT: }
+  #pragma omp declare simd
+  #pragma omp declare simd
+  int tadd(int b) { return x[b] + b; }
+
+private:
+  int x[10];
+};
+
+// CHECK: template <int X = 16> class TVV {
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: int tadd(int a, int b);
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: float taddpf(float *a, float *b) {
+// CHECK-NEXT: return *a + *b;
+// CHECK-NEXT: }
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: #pragma omp declare simd
+// CHECK-NEXT: int tadd(int b) {
+// CHECK-NEXT: return this->x[b] + b;
+// CHECK-NEXT: }
+// CHECK: }
+template <int X>
+class TVV {
+public:
+// CHECK: template <int X> class TVV {
+  #pragma omp declare simd
+  int tadd(int a, int b) { return a + b; }
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: int tadd(int a, int b) {
+// CHECK-NEXT: return a + b;
+// CHECK-NEXT: }
+
+  #pragma omp declare simd
+  float taddpf(float *a, float *b) { return *a + *b; }
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: float taddpf(float *a, float *b) {
+// CHECK-NEXT: return *a + *b;
+// CHECK-NEXT: }
+
+  #pragma omp declare simd
+  #pragma omp declare simd
+  int tadd(int b) { return x[b] + b; }
+
+// CHECK: #pragma omp declare simd
+// CHECK-NEXT: #pragma omp declare simd
+// CHECK-NEXT: int tadd(int b) {
+// CHECK-NEXT: return this->x[b] + b;
+// CHECK-NEXT: }
+
+private:
+  int x[X];
+};
+// CHECK: };
+
+// CHECK: TVV<16> t16;
+TVV<16> t16;
+
+void f() {
+  float a = 1.0f, b = 2.0f;
+  float r = t16.taddpf(&a, &b);
+  int res = t16.tadd(b);
+}
+
+#endif

Added: cfe/trunk/test/OpenMP/declare_simd_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_messages.cpp?rev=264853&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/declare_simd_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/declare_simd_messages.cpp Wed Mar 30 05:43:55 2016
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c++ -std=c++11 -fms-extensions %s
+
+// expected-error at +1 {{expected an OpenMP directive}}
+#pragma omp declare
+
+// expected-error at +2 {{'#pragma omp declare simd' can only be applied to functions}}
+#pragma omp declare simd
+int a;
+// expected-error at +2 {{'#pragma omp declare simd' can only be applied to functions}}
+#pragma omp declare simd
+#pragma omp threadprivate(a)
+int var;
+#pragma omp threadprivate(var)
+
+// expected-error at +2 {{expected an OpenMP directive}} expected-error at +1 {{function declaration is expected after 'declare simd' directive}}
+#pragma omp declare simd
+#pragma omp declare
+
+// expected-error at +3 {{function declaration is expected after 'declare simd' directive}}
+// expected-error at +1 {{function declaration is expected after 'declare simd' directive}}
+#pragma omp declare simd
+#pragma omp declare simd
+#pragma options align=packed
+int main();
+
+// expected-error at +3 {{function declaration is expected after 'declare simd' directive}}
+// expected-error at +1 {{function declaration is expected after 'declare simd' directive}}
+#pragma omp declare simd
+#pragma omp declare simd
+#pragma init_seg(compiler)
+int main();
+
+// expected-error at +1 {{single declaration is expected after 'declare simd' directive}}
+#pragma omp declare simd
+int b, c;
+
+#pragma omp declare simd
+template <class C>
+void h(C *hp, C *hp2, C *hq, C *lin) {
+  b = 0;
+}
+
+#pragma omp declare simd
+template <>
+void h(int *hp, int *hp2, int *hq, int *lin) {
+  h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
+}
+
+template <class T>
+struct St {
+// expected-error at +2 {{function declaration is expected after 'declare simd' directive}}
+#pragma init_seg(compiler)
+#pragma omp declare simd
+#pragma init_seg(compiler)
+  void h(T *hp) {
+// expected-error at +1 {{unexpected OpenMP directive '#pragma omp declare simd'}}
+#pragma omp declare simd
+    *hp = *t;
+  }
+
+private:
+  T t;
+};
+
+namespace N {
+  // expected-error at +1 {{function declaration is expected after 'declare simd' directive}}
+  #pragma omp declare simd
+}
+// expected-error at +1 {{function declaration is expected after 'declare simd' directive}}
+#pragma omp declare simd
+// expected-error at +1 {{function declaration is expected after 'declare simd' directive}}
+#pragma omp declare simd




More information about the cfe-commits mailing list