r211007 - [OPENMP] Initial support of 'reduction' clause

Alexey Bataev a.bataev at hotmail.com
Mon Jun 16 00:08:38 PDT 2014


Author: abataev
Date: Mon Jun 16 02:08:35 2014
New Revision: 211007

URL: http://llvm.org/viewvc/llvm-project?rev=211007&view=rev
Log:
[OPENMP] Initial support of 'reduction' clause

Added:
    cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/OpenMPClause.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/OpenMPKinds.def
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/Basic/OpenMPKinds.cpp
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/OpenMP/parallel_ast_print.cpp
    cfe/trunk/test/OpenMP/simd_aligned_messages.cpp
    cfe/trunk/test/OpenMP/simd_linear_messages.cpp
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Mon Jun 16 02:08:35 2014
@@ -2391,6 +2391,15 @@ bool RecursiveASTVisitor<Derived>::Visit
   return true;
 }
 
+template <typename Derived>
+bool DataRecursiveASTVisitor<Derived>::VisitOMPReductionClause(
+    OMPReductionClause *C) {
+  TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
+  TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
+  VisitOMPClauseList(C);
+  return true;
+}
+
 // FIXME: look at the following tricky-seeming exprs to see if we
 // need to recurse on anything.  These are ones that have methods
 // returning decls or qualtypes or nestednamespecifier -- though I'm

Modified: cfe/trunk/include/clang/AST/OpenMPClause.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OpenMPClause.h (original)
+++ cfe/trunk/include/clang/AST/OpenMPClause.h Mon Jun 16 02:08:35 2014
@@ -431,7 +431,8 @@ public:
   StmtRange children() { return StmtRange(); }
 };
 
-/// \brief This represents 'proc_bind' clause in the '#pragma omp ...' directive.
+/// \brief This represents 'proc_bind' clause in the '#pragma omp ...'
+/// directive.
 ///
 /// \code
 /// #pragma omp parallel proc_bind(master)
@@ -471,8 +472,8 @@ public:
   /// \param EndLoc Ending location of the clause.
   ///
   OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc,
-                   SourceLocation StartLoc, SourceLocation LParenLoc,
-                   SourceLocation EndLoc)
+                    SourceLocation StartLoc, SourceLocation LParenLoc,
+                    SourceLocation EndLoc)
       : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc),
         Kind(A), KindKwLoc(ALoc) {}
 
@@ -739,6 +740,99 @@ public:
   }
 };
 
+/// \brief This represents clause 'reduction' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp parallel reduction(+:a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'reduction'
+/// with operator '+' and the variables 'a' and 'b'.
+///
+class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
+  friend class OMPClauseReader;
+  /// \brief Location of ':'.
+  SourceLocation ColonLoc;
+  /// \brief Nested name specifier for C++.
+  NestedNameSpecifierLoc QualifierLoc;
+  /// \brief Name of custom operator.
+  DeclarationNameInfo NameInfo;
+
+  /// \brief Build clause with number of variables \a N.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param EndLoc Ending location of the clause.
+  /// \param ColonLoc Location of ':'.
+  /// \param N Number of the variables in the clause.
+  /// \param QualifierLoc The nested-name qualifier with location information
+  /// \param NameInfo The full name info for reduction identifier.
+  ///
+  OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+                     SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N,
+                     NestedNameSpecifierLoc QualifierLoc,
+                     const DeclarationNameInfo &NameInfo)
+      : OMPVarListClause<OMPReductionClause>(OMPC_reduction, StartLoc,
+                                             LParenLoc, EndLoc, N),
+        ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
+
+  /// \brief Build an empty clause.
+  ///
+  /// \param N Number of variables.
+  ///
+  explicit OMPReductionClause(unsigned N)
+      : OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(),
+                                             SourceLocation(), SourceLocation(),
+                                             N),
+        ColonLoc(), QualifierLoc(), NameInfo() {}
+
+  /// \brief Sets location of ':' symbol in clause.
+  void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
+  /// \brief Sets the name info for specified reduction identifier.
+  void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
+  /// \brief Sets the nested name specifier.
+  void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
+
+public:
+  /// \brief Creates clause with a list of variables \a VL.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param ColonLoc Location of ':'.
+  /// \param EndLoc Ending location of the clause.
+  /// \param N Number of the variables in the clause.
+  /// \param QualifierLoc The nested-name qualifier with location information
+  /// \param NameInfo The full name info for reduction identifier.
+  ///
+  static OMPReductionClause *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+         SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+         NestedNameSpecifierLoc QualifierLoc,
+         const DeclarationNameInfo &NameInfo);
+  /// \brief Creates an empty clause with the place for \a N variables.
+  ///
+  /// \param C AST context.
+  /// \param N The number of variables.
+  ///
+  static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+  /// \brief Gets location of ':' symbol in clause.
+  SourceLocation getColonLoc() const { return ColonLoc; }
+  /// \brief Gets the name info for specified reduction identifier.
+  const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+  /// \brief Gets the nested name specifier.
+  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+  StmtRange children() {
+    return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+                     reinterpret_cast<Stmt **>(varlist_end()));
+  }
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_reduction;
+  }
+};
+
 /// \brief This represents clause 'linear' in the '#pragma omp ...'
 /// directives.
 ///

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Jun 16 02:08:35 2014
@@ -2393,6 +2393,15 @@ bool RecursiveASTVisitor<Derived>::Visit
 }
 
 template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReductionClause(
+                                                    OMPReductionClause *C) {
+  TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
+  TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
+  VisitOMPClauseList(C);
+  return true;
+}
+
+template<typename Derived>
 bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
   VisitOMPClauseList(C);
   TraverseStmt(C->getStep());

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jun 16 02:08:35 2014
@@ -6965,6 +6965,8 @@ def err_omp_firstprivate_incomplete_type
   "a firstprivate variable with incomplete type %0">;
 def err_omp_lastprivate_incomplete_type : Error<
   "a lastprivate variable with incomplete type %0">;
+def err_omp_reduction_incomplete_type : Error<
+  "a reduction variable with incomplete type %0">;
 def err_omp_unexpected_clause_value : Error<
   "expected %0 in OpenMP clause '%1'">;
 def err_omp_expected_var_name : Error<
@@ -7044,6 +7046,24 @@ def err_omp_loop_cannot_use_stmt : Error
   "'%0' statement cannot be used in OpenMP for loop">;
 def err_omp_simd_region_cannot_use_stmt : Error<
   "'%0' statement cannot be used in OpenMP simd region">;
+def err_omp_unknown_reduction_identifier : Error<
+  "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">;
+def err_omp_reduction_type_array : Error<
+  "a reduction variable with array type %0">;
+def err_omp_reduction_ref_type_arg : Error<
+  "argument of OpenMP clause 'reduction' must reference the same object in all threads">;
+def err_omp_clause_not_arithmetic_type_arg : Error<
+  "arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of %select{scalar|arithmetic}0 type">;
+def err_omp_clause_floating_type_arg : Error<
+  "arguments of OpenMP clause 'reduction' with bitwise operators cannot be of floating type">;
+def err_omp_once_referenced : Error<
+  "variable can appear only once in OpenMP '%0' clause">;
+def note_omp_referenced : Note<
+  "previously referenced here">;
+def err_omp_reduction_in_task : Error<
+  "reduction variables may not be accessed in an explicit task">;
+def err_omp_reduction_id_not_compatible : Error<
+  "variable of type %0 is not valid for specified reduction operation">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {

Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Mon Jun 16 02:08:35 2014
@@ -47,6 +47,7 @@ OPENMP_CLAUSE(private, OMPPrivateClause)
 OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
 OPENMP_CLAUSE(lastprivate, OMPLastprivateClause)
 OPENMP_CLAUSE(shared,  OMPSharedClause)
+OPENMP_CLAUSE(reduction,  OMPReductionClause)
 OPENMP_CLAUSE(linear,  OMPLinearClause)
 OPENMP_CLAUSE(aligned, OMPAlignedClause)
 OPENMP_CLAUSE(copyin,  OMPCopyinClause)
@@ -60,6 +61,7 @@ OPENMP_PARALLEL_CLAUSE(proc_bind)
 OPENMP_PARALLEL_CLAUSE(private)
 OPENMP_PARALLEL_CLAUSE(firstprivate)
 OPENMP_PARALLEL_CLAUSE(shared)
+OPENMP_PARALLEL_CLAUSE(reduction)
 OPENMP_PARALLEL_CLAUSE(copyin)
 
 // FIXME: more clauses allowed for directive 'omp simd'.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jun 16 02:08:35 2014
@@ -7355,13 +7355,13 @@ public:
                                        SourceLocation LParenLoc,
                                        SourceLocation EndLoc);
 
-  OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
-                                      ArrayRef<Expr *> Vars,
-                                      Expr *TailExpr,
-                                      SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation ColonLoc,
-                                      SourceLocation EndLoc);
+  OMPClause *
+  ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars,
+                           Expr *TailExpr, SourceLocation StartLoc,
+                           SourceLocation LParenLoc, SourceLocation ColonLoc,
+                           SourceLocation EndLoc,
+                           CXXScopeSpec &ReductionIdScopeSpec,
+                           const DeclarationNameInfo &ReductionId);
   /// \brief Called on well-formed 'private' clause.
   OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
                                       SourceLocation StartLoc,
@@ -7382,6 +7382,13 @@ public:
                                      SourceLocation StartLoc,
                                      SourceLocation LParenLoc,
                                      SourceLocation EndLoc);
+  /// \brief Called on well-formed 'reduction' clause.
+  OMPClause *
+  ActOnOpenMPReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+                             SourceLocation LParenLoc, SourceLocation ColonLoc,
+                             SourceLocation EndLoc,
+                             CXXScopeSpec &ReductionIdScopeSpec,
+                             const DeclarationNameInfo &ReductionId);
   /// \brief Called on well-formed 'linear' clause.
   OMPClause *ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList,
                                      Expr *Step,

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Mon Jun 16 02:08:35 2014
@@ -1286,6 +1286,27 @@ void OMPExecutableDirective::setClauses(
   std::copy(Clauses.begin(), Clauses.end(), getClauses().begin());
 }
 
+OMPReductionClause *OMPReductionClause::Create(
+    const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+    SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+    NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) {
+  void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
+                                                  llvm::alignOf<Expr *>()) +
+                         sizeof(Expr *) * VL.size());
+  OMPReductionClause *Clause = new (Mem) OMPReductionClause(
+      StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
+  Clause->setVarRefs(VL);
+  return Clause;
+}
+
+OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
+                                                    unsigned N) {
+  void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
+                                                  llvm::alignOf<Expr *>()) +
+                         sizeof(Expr *) * N);
+  return new (Mem) OMPReductionClause(N);
+}
+
 OMPParallelDirective *OMPParallelDirective::Create(
                                               const ASTContext &C,
                                               SourceLocation StartLoc,

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Jun 16 02:08:35 2014
@@ -676,6 +676,28 @@ void OMPClausePrinter::VisitOMPSharedCla
   }
 }
 
+void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
+  if (!Node->varlist_empty()) {
+    OS << "reduction(";
+    NestedNameSpecifier *QualifierLoc =
+        Node->getQualifierLoc().getNestedNameSpecifier();
+    OverloadedOperatorKind OOK =
+        Node->getNameInfo().getName().getCXXOverloadedOperator();
+    if (QualifierLoc == nullptr && OOK != OO_None) {
+      // Print reduction identifier in C format
+      OS << getOperatorSpelling(OOK);
+    } else {
+      // Use C++ format
+      if (QualifierLoc != nullptr)
+        QualifierLoc->print(OS, Policy);
+      OS << Node->getNameInfo();
+    }
+    OS << ":";
+    VisitOMPClauseList(Node, ' ');
+    OS << ")";
+  }
+}
+
 void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
   if (!Node->varlist_empty()) {
     OS << "linear";

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Mon Jun 16 02:08:35 2014
@@ -308,6 +308,13 @@ OMPClauseProfiler::VisitOMPLastprivateCl
 void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
   VisitOMPClauseList(C);
 }
+void OMPClauseProfiler::VisitOMPReductionClause(
+                                         const OMPReductionClause *C) {
+  Profiler->VisitNestedNameSpecifier(
+      C->getQualifierLoc().getNestedNameSpecifier());
+  Profiler->VisitName(C->getNameInfo().getName());
+  VisitOMPClauseList(C);
+}
 void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
   VisitOMPClauseList(C);
   Profiler->VisitStmt(C->getStep());

Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Mon Jun 16 02:08:35 2014
@@ -88,6 +88,7 @@ unsigned clang::getOpenMPSimpleClauseTyp
   case OMPC_firstprivate:
   case OMPC_lastprivate:
   case OMPC_shared:
+  case OMPC_reduction:
   case OMPC_linear:
   case OMPC_aligned:
   case OMPC_copyin:
@@ -127,6 +128,7 @@ const char *clang::getOpenMPSimpleClause
   case OMPC_firstprivate:
   case OMPC_lastprivate:
   case OMPC_shared:
+  case OMPC_reduction:
   case OMPC_linear:
   case OMPC_aligned:
   case OMPC_copyin:

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Mon Jun 16 02:08:35 2014
@@ -258,7 +258,8 @@ bool Parser::ParseOpenMPSimpleVarList(Op
 ///    clause:
 ///       if-clause | num_threads-clause | safelen-clause | default-clause |
 ///       private-clause | firstprivate-clause | shared-clause | linear-clause |
-///       aligned-clause | collapse-clause | lastprivate-clause
+///       aligned-clause | collapse-clause | lastprivate-clause |
+///       reduction-clause
 ///
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                      OpenMPClauseKind CKind, bool FirstClause) {
@@ -307,6 +308,7 @@ OMPClause *Parser::ParseOpenMPClause(Ope
   case OMPC_firstprivate:
   case OMPC_lastprivate:
   case OMPC_shared:
+  case OMPC_reduction:
   case OMPC_linear:
   case OMPC_aligned:
   case OMPC_copyin:
@@ -394,6 +396,52 @@ OMPClause *Parser::ParseOpenMPSimpleClau
                                          Tok.getLocation());
 }
 
+static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
+                             UnqualifiedId &ReductionId) {
+  SourceLocation TemplateKWLoc;
+  if (ReductionIdScopeSpec.isEmpty()) {
+    auto OOK = OO_None;
+    switch (P.getCurToken().getKind()) {
+    case tok::plus:
+      OOK = OO_Plus;
+      break;
+    case tok::minus:
+      OOK = OO_Minus;
+      break;
+    case tok::star:
+      OOK = OO_Star;
+      break;
+    case tok::amp:
+      OOK = OO_Amp;
+      break;
+    case tok::pipe:
+      OOK = OO_Pipe;
+      break;
+    case tok::caret:
+      OOK = OO_Caret;
+      break;
+    case tok::ampamp:
+      OOK = OO_AmpAmp;
+      break;
+    case tok::pipepipe:
+      OOK = OO_PipePipe;
+      break;
+    default:
+      break;
+    }
+    if (OOK != OO_None) {
+      SourceLocation OpLoc = P.ConsumeToken();
+      SourceLocation SymbolLocations[] = { OpLoc, OpLoc, SourceLocation() };
+      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
+      return false;
+    }
+  }
+  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
+                              /*AllowDestructorName*/ false,
+                              /*AllowConstructorName*/ false, ParsedType(),
+                              TemplateKWLoc, ReductionId);
+}
+
 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
 /// 'shared', 'copyin', or 'reduction'.
 ///
@@ -409,19 +457,44 @@ OMPClause *Parser::ParseOpenMPSimpleClau
 ///       'linear' '(' list [ ':' linear-step ] ')'
 ///    aligned-clause:
 ///       'aligned' '(' list [ ':' alignment ] ')'
+///    reduction-clause:
+///       'reduction' '(' reduction-identifier ':' list ')'
 ///
 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
   SourceLocation Loc = Tok.getLocation();
   SourceLocation LOpen = ConsumeToken();
   SourceLocation ColonLoc = SourceLocation();
+  // Optional scope specifier and unqualified id for reduction identifier.
+  CXXScopeSpec ReductionIdScopeSpec;
+  UnqualifiedId ReductionId;
+  bool InvalidReductionId = false;
   // Parse '('.
   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
   if (T.expectAndConsume(diag::err_expected_lparen_after,
                          getOpenMPClauseName(Kind)))
     return nullptr;
 
+  // Handle reduction-identifier for reduction clause.
+  if (Kind == OMPC_reduction) {
+    ColonProtectionRAIIObject ColonRAII(*this);
+    if (getLangOpts().CPlusPlus) {
+      ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
+    }
+    InvalidReductionId =
+        ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
+    if (InvalidReductionId) {
+      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+                StopBeforeMatch);
+    }
+    if (Tok.is(tok::colon)) {
+      ColonLoc = ConsumeToken();
+    } else {
+      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
+    }
+  }
+
   SmallVector<Expr *, 5> Vars;
-  bool IsComma = true;
+  bool IsComma = !InvalidReductionId;
   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                      Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -460,10 +533,13 @@ OMPClause *Parser::ParseOpenMPVarListCla
 
   // Parse ')'.
   T.consumeClose();
-  if (Vars.empty() || (MustHaveTail && !TailExpr))
+  if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
     return nullptr;
 
-  return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen,
-                                          ColonLoc, Tok.getLocation());
+  return Actions.ActOnOpenMPVarListClause(
+      Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
+      ReductionIdScopeSpec,
+      ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
+                            : DeclarationNameInfo());
 }
 

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Mon Jun 16 02:08:35 2014
@@ -119,6 +119,10 @@ public:
   /// attribute in \a DKind directive.
   DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
                     OpenMPDirectiveKind DKind = OMPD_unknown);
+  /// \brief Checks if the specified variables has \a CKind data-sharing
+  /// attribute in an innermost \a DKind directive.
+  DSAVarData hasInnermostDSA(VarDecl *D, OpenMPClauseKind CKind,
+                             OpenMPDirectiveKind DKind);
 
   /// \brief Returns currently analyzed directive.
   OpenMPDirectiveKind getCurrentDirective() const {
@@ -154,7 +158,6 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
     //  File-scope or namespace-scope variables referenced in called routines
     //  in the region are shared unless they appear in a threadprivate
     //  directive.
-    // TODO
     if (!D->isFunctionOrMethodVarDecl())
       DVar.CKind = OMPC_shared;
 
@@ -214,7 +217,6 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
     //  In a task construct, if no default clause is present, a variable that in
     //  the enclosing context is determined to be shared by all implicit tasks
     //  bound to the current team is shared.
-    // TODO
     if (DVar.DKind == OMPD_task) {
       DSAVarData DVarTemp;
       for (StackTy::reverse_iterator I = std::next(Iter),
@@ -399,6 +401,21 @@ DSAStackTy::DSAVarData DSAStackTy::hasDS
   return DSAVarData();
 }
 
+DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(VarDecl *D,
+                                                   OpenMPClauseKind CKind,
+                                                   OpenMPDirectiveKind DKind) {
+  assert(DKind != OMPD_unknown && "Directive must be specified explicitly");
+  for (auto I = Stack.rbegin(), EE = std::prev(Stack.rend()); I != EE; ++I) {
+    if (DKind != I->Directive)
+      continue;
+    DSAVarData DVar = getDSA(I, D);
+    if (DVar.CKind == CKind)
+      return DVar;
+    return DSAVarData();
+  }
+  return DSAVarData();
+}
+
 void Sema::InitDataSharingAttributesStack() {
   VarDataSharingAttributesStack = new DSAStackTy(*this);
 }
@@ -702,7 +719,16 @@ public:
       //  A list item that appears in a reduction clause of the innermost
       //  enclosing worksharing or parallel construct may not be accessed in an
       //  explicit task.
-      // TODO:
+      DVar = Stack->hasInnermostDSA(VD, OMPC_reduction, OMPD_parallel);
+      if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
+        ErrorFound = true;
+        Actions.Diag(ELoc, diag::err_omp_reduction_in_task);
+        if (DVar.RefExpr) {
+          Actions.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+              << getOpenMPClauseName(OMPC_reduction);
+        }
+        return;
+      }
 
       // Define implicit data-sharing attributes for task.
       DVar = Stack->getImplicitDSA(VD);
@@ -1357,6 +1383,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprCl
   case OMPC_firstprivate:
   case OMPC_lastprivate:
   case OMPC_shared:
+  case OMPC_reduction:
   case OMPC_linear:
   case OMPC_aligned:
   case OMPC_copyin:
@@ -1532,6 +1559,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause
   case OMPC_firstprivate:
   case OMPC_lastprivate:
   case OMPC_shared:
+  case OMPC_reduction:
   case OMPC_linear:
   case OMPC_aligned:
   case OMPC_copyin:
@@ -1617,11 +1645,11 @@ OMPClause *Sema::ActOnOpenMPProcBindClau
       OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
 }
 
-OMPClause *
-Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> VarList,
-                               Expr *TailExpr, SourceLocation StartLoc,
-                               SourceLocation LParenLoc,
-                               SourceLocation ColonLoc, SourceLocation EndLoc) {
+OMPClause *Sema::ActOnOpenMPVarListClause(
+    OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
+    SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
+    SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
+    const DeclarationNameInfo &ReductionId) {
   OMPClause *Res = nullptr;
   switch (Kind) {
   case OMPC_private:
@@ -1636,6 +1664,11 @@ Sema::ActOnOpenMPVarListClause(OpenMPCla
   case OMPC_shared:
     Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
     break;
+  case OMPC_reduction:
+    Res =
+        ActOnOpenMPReductionClause(VarList, StartLoc, LParenLoc, ColonLoc,
+                                   EndLoc, ReductionIdScopeSpec, ReductionId);
+    break;
   case OMPC_linear:
     Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
                                   ColonLoc, EndLoc);
@@ -2194,6 +2227,323 @@ OMPClause *Sema::ActOnOpenMPSharedClause
   return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
 }
 
+namespace {
+class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
+  DSAStackTy *Stack;
+
+public:
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+    if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+      DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
+      if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
+        return false;
+      if (DVar.CKind != OMPC_unknown)
+        return true;
+      DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(VD, OMPC_private);
+      DSAStackTy::DSAVarData DVarFirstprivate =
+          Stack->hasDSA(VD, OMPC_firstprivate);
+      DSAStackTy::DSAVarData DVarReduction = Stack->hasDSA(VD, OMPC_reduction);
+      if (DVarPrivate.CKind != OMPC_unknown ||
+          DVarFirstprivate.CKind != OMPC_unknown ||
+          DVarReduction.CKind != OMPC_unknown)
+        return true;
+      return false;
+    }
+    return false;
+  }
+  bool VisitStmt(Stmt *S) {
+    for (auto Child : S->children()) {
+      if (Child && Visit(Child))
+        return true;
+    }
+    return false;
+  }
+  DSARefChecker(DSAStackTy *S) : Stack(S) {}
+};
+}
+
+OMPClause *Sema::ActOnOpenMPReductionClause(
+    ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
+    SourceLocation ColonLoc, SourceLocation EndLoc,
+    CXXScopeSpec &ReductionIdScopeSpec,
+    const DeclarationNameInfo &ReductionId) {
+  // TODO: Allow scope specification search when 'declare reduction' is
+  // supported.
+  assert(ReductionIdScopeSpec.isEmpty() &&
+         "No support for scoped reduction identifiers yet.");
+
+  auto DN = ReductionId.getName();
+  auto OOK = DN.getCXXOverloadedOperator();
+  BinaryOperatorKind BOK = BO_Comma;
+
+  // OpenMP [2.14.3.6, reduction clause]
+  // C
+  // reduction-identifier is either an identifier or one of the following
+  // operators: +, -, *,  &, |, ^, && and ||
+  // C++
+  // reduction-identifier is either an id-expression or one of the following
+  // operators: +, -, *, &, |, ^, && and ||
+  // FIXME: Only 'min' and 'max' identifiers are supported for now.
+  switch (OOK) {
+  case OO_Plus:
+  case OO_Minus:
+    BOK = BO_AddAssign;
+    break;
+  case OO_Star:
+    BOK = BO_MulAssign;
+    break;
+  case OO_Amp:
+    BOK = BO_AndAssign;
+    break;
+  case OO_Pipe:
+    BOK = BO_OrAssign;
+    break;
+  case OO_Caret:
+    BOK = BO_XorAssign;
+    break;
+  case OO_AmpAmp:
+    BOK = BO_LAnd;
+    break;
+  case OO_PipePipe:
+    BOK = BO_LOr;
+    break;
+  default:
+    if (auto II = DN.getAsIdentifierInfo()) {
+      if (II->isStr("max"))
+        BOK = BO_GT;
+      else if (II->isStr("min"))
+        BOK = BO_LT;
+    }
+    break;
+  }
+  SourceRange ReductionIdRange;
+  if (ReductionIdScopeSpec.isValid()) {
+    ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
+  }
+  ReductionIdRange.setEnd(ReductionId.getEndLoc());
+  if (BOK == BO_Comma) {
+    // Not allowed reduction identifier is found.
+    Diag(ReductionId.getLocStart(), diag::err_omp_unknown_reduction_identifier)
+        << ReductionIdRange;
+    return nullptr;
+  }
+
+  SmallVector<Expr *, 8> Vars;
+  for (auto RefExpr : VarList) {
+    assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
+    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+      // It will be analyzed later.
+      Vars.push_back(RefExpr);
+      continue;
+    }
+
+    if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
+        RefExpr->isInstantiationDependent() ||
+        RefExpr->containsUnexpandedParameterPack()) {
+      // It will be analyzed later.
+      Vars.push_back(RefExpr);
+      continue;
+    }
+
+    auto ELoc = RefExpr->getExprLoc();
+    auto ERange = RefExpr->getSourceRange();
+    // OpenMP [2.1, C/C++]
+    //  A list item is a variable or array section, subject to the restrictions
+    //  specified in Section 2.4 on page 42 and in each of the sections
+    // describing clauses and directives for which a list appears.
+    // OpenMP  [2.14.3.3, Restrictions, p.1]
+    //  A variable that is part of another variable (as an array or
+    //  structure element) cannot appear in a private clause.
+    auto DE = dyn_cast<DeclRefExpr>(RefExpr);
+    if (!DE || !isa<VarDecl>(DE->getDecl())) {
+      Diag(ELoc, diag::err_omp_expected_var_name) << ERange;
+      continue;
+    }
+    auto D = DE->getDecl();
+    auto VD = cast<VarDecl>(D);
+    auto Type = VD->getType();
+    // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
+    //  A variable that appears in a private clause must not have an incomplete
+    //  type or a reference type.
+    if (RequireCompleteType(ELoc, Type,
+                            diag::err_omp_reduction_incomplete_type))
+      continue;
+    // OpenMP [2.14.3.6, reduction clause, Restrictions]
+    // Arrays may not appear in a reduction clause.
+    if (Type.getNonReferenceType()->isArrayType()) {
+      Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange;
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+    // OpenMP [2.14.3.6, reduction clause, Restrictions]
+    // A list item that appears in a reduction clause must not be
+    // const-qualified.
+    if (Type.getNonReferenceType().isConstant(Context)) {
+      Diag(ELoc, diag::err_omp_const_variable)
+          << getOpenMPClauseName(OMPC_reduction) << Type << ERange;
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+    // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
+    //  If a list-item is a reference type then it must bind to the same object
+    //  for all threads of the team.
+    VarDecl *VDDef = VD->getDefinition();
+    if (Type->isReferenceType() && VDDef) {
+      DSARefChecker Check(DSAStack);
+      if (Check.Visit(VDDef->getInit())) {
+        Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
+        Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
+        continue;
+      }
+    }
+    // OpenMP [2.14.3.6, reduction clause, Restrictions]
+    // The type of a list item that appears in a reduction clause must be valid
+    // for the reduction-identifier. For a max or min reduction in C, the type
+    // of the list item must be an allowed arithmetic data type: char, int,
+    // float, double, or _Bool, possibly modified with long, short, signed, or
+    // unsigned. For a max or min reduction in C++, the type of the list item
+    // must be an allowed arithmetic data type: char, wchar_t, int, float,
+    // double, or bool, possibly modified with long, short, signed, or unsigned.
+    if ((BOK == BO_GT || BOK == BO_LT) &&
+        !(Type->isScalarType() ||
+          (getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
+      Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
+          << getLangOpts().CPlusPlus;
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+    if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
+        !getLangOpts().CPlusPlus && Type->isFloatingType()) {
+      Diag(ELoc, diag::err_omp_clause_floating_type_arg);
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+    bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
+    getDiagnostics().setSuppressAllDiagnostics(true);
+    ExprResult ReductionOp =
+        BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
+                   RefExpr, RefExpr);
+    getDiagnostics().setSuppressAllDiagnostics(Suppress);
+    if (ReductionOp.isInvalid()) {
+      Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
+          << ReductionIdRange;
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+
+    // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
+    // in a Construct]
+    //  Variables with the predetermined data-sharing attributes may not be
+    //  listed in data-sharing attributes clauses, except for the cases
+    //  listed below. For these exceptions only, listing a predetermined
+    //  variable in a data-sharing attribute clause is allowed and overrides
+    //  the variable's predetermined data-sharing attributes.
+    // OpenMP [2.14.3.6, Restrictions, p.3]
+    //  Any number of reduction clauses can be specified on the directive,
+    //  but a list item can appear only once in the reduction clauses for that
+    //  directive.
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    if (DVar.CKind == OMPC_reduction) {
+      Diag(ELoc, diag::err_omp_once_referenced)
+          << getOpenMPClauseName(OMPC_reduction);
+      if (DVar.RefExpr) {
+        Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
+      }
+    } else if (DVar.CKind != OMPC_unknown) {
+      Diag(ELoc, diag::err_omp_wrong_dsa)
+          << getOpenMPClauseName(DVar.CKind)
+          << getOpenMPClauseName(OMPC_reduction);
+      if (DVar.RefExpr) {
+        Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+            << getOpenMPClauseName(DVar.CKind);
+      } else {
+        Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
+            << getOpenMPClauseName(DVar.CKind);
+      }
+      continue;
+    }
+
+    // OpenMP [2.14.3.6, Restrictions, p.1]
+    //  A list item that appears in a reduction clause of a worksharing
+    //  construct must be shared in the parallel regions to which any of the
+    //  worksharing regions arising from the worksharing construct bind.
+    // TODO Implement it later.
+
+    CXXRecordDecl *RD = getLangOpts().CPlusPlus
+                            ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+                            : nullptr;
+    if (RD) {
+      CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
+      PartialDiagnostic PD =
+          PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+      if (!CD || CheckConstructorAccess(
+                     ELoc, CD, InitializedEntity::InitializeTemporary(Type),
+                     CD->getAccess(), PD) == AR_inaccessible ||
+          CD->isDeleted()) {
+        Diag(ELoc, diag::err_omp_required_method)
+            << getOpenMPClauseName(OMPC_reduction) << 0;
+        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                      VarDecl::DeclarationOnly;
+        Diag(VD->getLocation(),
+             IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+            << VD;
+        Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+        continue;
+      }
+      MarkFunctionReferenced(ELoc, CD);
+      DiagnoseUseOfDecl(CD, ELoc);
+
+      CXXDestructorDecl *DD = RD->getDestructor();
+      if (DD) {
+        if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
+            DD->isDeleted()) {
+          Diag(ELoc, diag::err_omp_required_method)
+              << getOpenMPClauseName(OMPC_reduction) << 4;
+          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                        VarDecl::DeclarationOnly;
+          Diag(VD->getLocation(),
+               IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+              << VD;
+          Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+          continue;
+        }
+        MarkFunctionReferenced(ELoc, DD);
+        DiagnoseUseOfDecl(DD, ELoc);
+      }
+    }
+
+    DSAStack->addDSA(VD, DE, OMPC_reduction);
+    Vars.push_back(DE);
+  }
+
+  if (Vars.empty())
+    return nullptr;
+
+  return OMPReductionClause::Create(
+      Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
+      ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId);
+}
+
 OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
                                          SourceLocation StartLoc,
                                          SourceLocation LParenLoc,

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Jun 16 02:08:35 2014
@@ -1425,6 +1425,22 @@ public:
                                              EndLoc);
   }
 
+  /// \brief Build a new OpenMP 'reduction' clause.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OMPClause *RebuildOMPReductionClause(ArrayRef<Expr *> VarList,
+                                       SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation ColonLoc,
+                                       SourceLocation EndLoc,
+                                       CXXScopeSpec &ReductionIdScopeSpec,
+                                       const DeclarationNameInfo &ReductionId) {
+    return getSema().ActOnOpenMPReductionClause(
+        VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec,
+        ReductionId);
+  }
+
   /// \brief Build a new OpenMP 'linear' clause.
   ///
   /// By default, performs semantic analysis to build the new OpenMP clause.
@@ -6348,10 +6364,8 @@ StmtResult TreeTransform<Derived>::Trans
        I != E; ++I) {
     if (*I) {
       OMPClause *Clause = getDerived().TransformOMPClause(*I);
-      if (!Clause) {
-        return StmtError();
-      }
-      TClauses.push_back(Clause);
+      if (Clause)
+        TClauses.push_back(Clause);
     } else {
       TClauses.push_back(nullptr);
     }
@@ -6361,7 +6375,7 @@ StmtResult TreeTransform<Derived>::Trans
   }
   StmtResult AssociatedStmt =
       getDerived().TransformStmt(D->getAssociatedStmt());
-  if (AssociatedStmt.isInvalid()) {
+  if (AssociatedStmt.isInvalid() || TClauses.size() != Clauses.size()) {
     return StmtError();
   }
 
@@ -6510,6 +6524,31 @@ TreeTransform<Derived>::TransformOMPShar
 
 template <typename Derived>
 OMPClause *
+TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
+  llvm::SmallVector<Expr *, 16> Vars;
+  Vars.reserve(C->varlist_size());
+  for (auto *VE : C->varlists()) {
+    ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+    if (EVar.isInvalid())
+      return nullptr;
+    Vars.push_back(EVar.get());
+  }
+  CXXScopeSpec ReductionIdScopeSpec;
+  ReductionIdScopeSpec.Adopt(C->getQualifierLoc());
+
+  DeclarationNameInfo NameInfo = C->getNameInfo();
+  if (NameInfo.getName()) {
+    NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+    if (!NameInfo.getName())
+      return nullptr;
+  }
+  return getDerived().RebuildOMPReductionClause(
+      Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
+      C->getLocEnd(), ReductionIdScopeSpec, NameInfo);
+}
+
+template <typename Derived>
+OMPClause *
 TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
   llvm::SmallVector<Expr *, 16> Vars;
   Vars.reserve(C->varlist_size());
@@ -10017,7 +10056,11 @@ TreeTransform<Derived>::TransformCapture
   }
   getSema().ActOnCapturedRegionStart(Loc, /*CurScope*/nullptr,
                                      S->getCapturedRegionKind(), Params);
-  StmtResult Body = getDerived().TransformStmt(S->getCapturedStmt());
+  StmtResult Body;
+  {
+    Sema::CompoundScopeRAII CompoundScope(getSema());
+    Body = getDerived().TransformStmt(S->getCapturedStmt());
+  }
 
   if (Body.isInvalid()) {
     getSema().ActOnCapturedRegionError();

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Jun 16 02:08:35 2014
@@ -1703,6 +1703,9 @@ OMPClause *OMPClauseReader::readClause()
   case OMPC_shared:
     C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
     break;
+  case OMPC_reduction:
+    C = OMPReductionClause::CreateEmpty(Context, Record[Idx++]);
+    break;
   case OMPC_linear:
     C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]);
     break;
@@ -1789,6 +1792,24 @@ void OMPClauseReader::VisitOMPSharedClau
   unsigned NumVars = C->varlist_size();
   SmallVector<Expr *, 16> Vars;
   Vars.reserve(NumVars);
+  for (unsigned i = 0; i != NumVars; ++i)
+    Vars.push_back(Reader->Reader.ReadSubExpr());
+  C->setVarRefs(Vars);
+}
+
+void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
+  C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+  C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+  NestedNameSpecifierLoc NNSL =
+    Reader->Reader.ReadNestedNameSpecifierLoc(Reader->F, Record, Idx);
+  DeclarationNameInfo DNI;
+  Reader->ReadDeclarationNameInfo(DNI, Record, Idx);
+  C->setQualifierLoc(NNSL);
+  C->setNameInfo(DNI);
+
+  unsigned NumVars = C->varlist_size();
+  SmallVector<Expr *, 16> Vars;
+  Vars.reserve(NumVars);
   for (unsigned i = 0; i != NumVars; ++i)
     Vars.push_back(Reader->Reader.ReadSubExpr());
   C->setVarRefs(Vars);

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Jun 16 02:08:35 2014
@@ -1735,6 +1735,16 @@ void OMPClauseWriter::VisitOMPSharedClau
     Writer->Writer.AddStmt(VE);
 }
 
+void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
+  Record.push_back(C->varlist_size());
+  Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+  Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+  Writer->Writer.AddNestedNameSpecifierLoc(C->getQualifierLoc(), Record);
+  Writer->Writer.AddDeclarationNameInfo(C->getNameInfo(), Record);
+  for (auto *VE : C->varlists())
+    Writer->Writer.AddStmt(VE);
+}
+
 void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
   Record.push_back(C->varlist_size());
   Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);

Modified: cfe/trunk/test/OpenMP/parallel_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_ast_print.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_ast_print.cpp Mon Jun 16 02:08:35 2014
@@ -35,9 +35,9 @@ T tmain(T argc, T *argv) {
   S<T> s;
 #pragma omp parallel
   a=2;
-#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master)
+#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master) reduction(+:c) reduction(max:e)
   foo();
-#pragma omp parallel if (C) num_threads(s) proc_bind(close)
+#pragma omp parallel if (C) num_threads(s) proc_bind(close) reduction(^:e, f) reduction(&& : g)
   foo();
   return 0;
 }
@@ -48,9 +48,9 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: S<int> s;
 // CHECK-NEXT: #pragma omp parallel
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close)
+// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
 // CHECK-NEXT: long b = argc, c, d, e, f, g;
@@ -58,9 +58,9 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: S<long> s;
 // CHECK-NEXT: #pragma omp parallel
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close)
+// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g)
 // CHECK-NEXT: foo()
 // CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
 // CHECK-NEXT: T b = argc, c, d, e, f, g;
@@ -68,9 +68,9 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: S<T> s;
 // CHECK-NEXT: #pragma omp parallel
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close)
+// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g)
 // CHECK-NEXT: foo()
 
 enum Enum { };
@@ -86,8 +86,8 @@ int main (int argc, char **argv) {
 // CHECK-NEXT: #pragma omp parallel
   a=2;
 // CHECK-NEXT: a = 2;
-#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a) proc_bind(spread)
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a) proc_bind(spread)
+#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(| : c, d) reduction(* : e)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(|: c,d) reduction(*: e)
   foo();
 // CHECK-NEXT: foo();
   return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);

Added: cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp?rev=211007&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp Mon Jun 16 02:08:35 2014
@@ -0,0 +1,215 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+  return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+  mutable int a;
+  S2 &operator +=(const S2 &arg) {return (*this);}
+public:
+  S2():a(0) { }
+  S2(S2 &s2):a(s2.a) { }
+  static float S2s; // expected-note 2 {{predetermined as shared}}
+  static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+  int a;
+public:
+  S3():a(0) { }
+  S3(const S3 &s3):a(s3.a) { }
+  S3 operator +=(const S3 &arg1) {return arg1;}
+};
+int operator +=(const S3 &arg1, const S3 &arg2) {return 5;}
+S3 c; // expected-note 2 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 { // expected-note {{'S4' declared here}}
+  int a;
+  S4();
+  S4(const S4 &s4);
+  S4 &operator +=(const S4 &arg) {return (*this);}
+public:
+  S4(int v):a(v) { }
+};
+S4 &operator &=(S4 &arg1, S4 &arg2) {return arg1;}
+class S5 {
+  int a;
+  S5():a(0) {}
+  S5(const S5 &s5):a(s5.a) { }
+  S5 &operator +=(const S5 &arg);
+public:
+  S5(int v):a(v) { }
+};
+class S6 {
+    int a;
+  public:
+    S6():a(6){ }
+    operator int() { return 6; }
+} o; // expected-note 2 {{'o' defined here}}
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) { // expected-note 2 {{'argc' defined here}}
+  const T d = T(); // expected-note 4 {{'d' defined here}}
+  const T da[5] = { T() }; // expected-note 2 {{'da' defined here}}
+  T qa[5] = { T() };
+  T i;
+  T &j = i; // expected-note 4 {{'j' defined here}}
+  S3 &p = k; // expected-note 2 {{'p' defined here}}
+  const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+  T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+  T fl; // expected-note {{'fl' defined here}}
+  #pragma omp parallel reduction // expected-error {{expected '(' after 'reduction'}}
+  foo();
+  #pragma omp parallel reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
+  foo();
+  #pragma omp parallel reduction ( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+  #pragma omp parallel reduction (- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+  #pragma omp parallel reduction () // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+  foo();
+  #pragma omp parallel reduction (*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+  foo();
+  #pragma omp parallel reduction (\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+  foo();
+  #pragma omp parallel reduction (&: argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel reduction (| :argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel reduction (|| :argc ? i : argc) // expected-error 2 {{expected variable name}}
+  foo();
+  #pragma omp parallel reduction (foo:argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+  foo();
+  #pragma omp parallel reduction (&& :argc)
+  foo();
+  #pragma omp parallel reduction (^ : T) // expected-error {{'T' does not refer to a value}}
+  foo();
+  #pragma omp parallel reduction (+ : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction (min : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction (max : qa[1]) // expected-error 2 {{expected variable name}}
+  foo();
+  #pragma omp parallel reduction(+ : ba) // expected-error {{a reduction variable with array type 'const S2 [5]'}}
+  foo();
+  #pragma omp parallel reduction(* : ca) // expected-error {{a reduction variable with array type 'const S3 [5]'}}
+  foo();
+  #pragma omp parallel reduction(- : da) // expected-error {{a reduction variable with array type 'const int [5]'}} expected-error {{a reduction variable with array type 'const float [5]'}}
+  foo();
+  #pragma omp parallel reduction(^ : fl) // expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction(+ : o) // expected-error {{variable of type 'class S6' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel private(i), reduction(+ : j), reduction(+:q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+  foo();
+  #pragma omp parallel private(k)
+  #pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+  foo();
+  #pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
+  foo();
+  #pragma omp parallel reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel shared(i)
+  #pragma omp parallel reduction(min : i)
+  #pragma omp parallel reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+  foo();
+
+  return T();
+}
+
+int main(int argc, char **argv) {
+  const int d = 5; // expected-note 2 {{'d' defined here}}
+  const int da[5] = { 0 }; // expected-note {{'da' defined here}}
+  int qa[5] = { 0 };
+  S4 e(4); // expected-note {{'e' defined here}}
+  S5 g(5); // expected-note {{'g' defined here}}
+  int i;
+  int &j = i; // expected-note 2 {{'j' defined here}}
+  S3 &p = k; // expected-note 2 {{'p' defined here}}
+  const int &r = da[i]; // expected-note {{'r' defined here}}
+  int &q = qa[i]; // expected-note {{'q' defined here}}
+  float fl; // expected-note {{'fl' defined here}}
+  #pragma omp parallel reduction // expected-error {{expected '(' after 'reduction'}}
+  foo();
+  #pragma omp parallel reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
+  foo();
+  #pragma omp parallel reduction ( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+  #pragma omp parallel reduction (- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+  #pragma omp parallel reduction () // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+  foo();
+  #pragma omp parallel reduction (*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+  foo();
+  #pragma omp parallel reduction (\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+  foo();
+  #pragma omp parallel reduction (foo: argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+  foo();
+  #pragma omp parallel reduction (| :argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+  #pragma omp parallel reduction (|| :argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  foo();
+  #pragma omp parallel reduction (~:argc) // expected-error {{expected unqualified-id}}
+  foo();
+  #pragma omp parallel reduction (&& :argc)
+  foo();
+  #pragma omp parallel reduction (^ : S1) // expected-error {{'S1' does not refer to a value}}
+  foo();
+  #pragma omp parallel reduction (+ : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction (min : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction (max : argv[1]) // expected-error {{expected variable name}}
+  foo();
+  #pragma omp parallel reduction(+ : ba) // expected-error {{a reduction variable with array type 'const S2 [5]'}}
+  foo();
+  #pragma omp parallel reduction(* : ca) // expected-error {{a reduction variable with array type 'const S3 [5]'}}
+  foo();
+  #pragma omp parallel reduction(- : da) // expected-error {{a reduction variable with array type 'const int [5]'}}
+  foo();
+  #pragma omp parallel reduction(^ : fl) // expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction(& : e, g) // expected-error {{reduction variable must have an accessible, unambiguous default constructor}} expected-error {{variable of type 'S5' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+  foo();
+  #pragma omp parallel reduction(+ : o) // expected-error {{variable of type 'class S6' is not valid for specified reduction operation}}
+  foo();
+  #pragma omp parallel private(i), reduction(+ : j), reduction(+:q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+  foo();
+  #pragma omp parallel private(k)
+  #pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+  foo();
+  #pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+  foo();
+  #pragma omp parallel reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
+  foo();
+  #pragma omp parallel shared(i)
+  #pragma omp parallel reduction(min : i)
+  #pragma omp parallel reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+  foo();
+
+  return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}

Propchange: cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/parallel_reduction_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/OpenMP/simd_aligned_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_aligned_messages.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/simd_aligned_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/simd_aligned_messages.cpp Mon Jun 16 02:08:35 2014
@@ -52,13 +52,14 @@ template<int L, class T, class N> T test
   // expected-error at +1 {{argument to 'aligned' clause must be a positive integer value}}
   #pragma omp simd aligned(arr:L)
   for (i = 0; i < num; ++i) {
-    T cur = arr[ind2];
+    T cur = arr[(int)ind2];
     ind2 += L;
     sum += cur;
   }
   // expected-error at +1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
   #pragma omp simd aligned(num:4)
   for (i = 0; i < num; ++i);
+  return T();
 }
 
 template<int LEN> int test_warn() {

Modified: cfe/trunk/test/OpenMP/simd_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_linear_messages.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/simd_linear_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/simd_linear_messages.cpp Mon Jun 16 02:08:35 2014
@@ -50,10 +50,11 @@ template<int L, class T, class N> T test
   // expected-error at +1 {{argument of a linear clause should be of integral or pointer type}}
 #pragma omp simd linear(ind2:L)
   for (i = 0; i < num; ++i) {
-    T cur = arr[ind2];
+    T cur = arr[(int)ind2];
     ind2 += L;
     sum += cur;
   }
+  return T();
 }
 
 template<int LEN> int test_warn() {

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=211007&r1=211006&r2=211007&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Jun 16 02:08:35 2014
@@ -1963,6 +1963,9 @@ void OMPClauseEnqueue::VisitOMPLastpriva
 void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
   VisitOMPClauseList(C);
 }
+void OMPClauseEnqueue::VisitOMPReductionClause(const OMPReductionClause *C) {
+  VisitOMPClauseList(C);
+}
 void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
   VisitOMPClauseList(C);
   Visitor->AddStmt(C->getStep());





More information about the cfe-commits mailing list