r206891 - [OPENMP] parsing 'linear' clause (for directive 'omp simd')

Alexander Musman alexander.musman at gmail.com
Tue Apr 22 06:09:42 PDT 2014


Author: amusman
Date: Tue Apr 22 08:09:42 2014
New Revision: 206891

URL: http://llvm.org/viewvc/llvm-project?rev=206891&view=rev
Log:
[OPENMP] parsing 'linear' clause (for directive 'omp simd')

Differential Revision: http://reviews.llvm.org/D3272


Added:
    cfe/trunk/test/OpenMP/simd_linear_messages.cpp
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/DiagnosticGroups.td
    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/simd_ast_print.cpp
    cfe/trunk/test/OpenMP/simd_misc_messages.c
    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=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Tue Apr 22 08:09:42 2014
@@ -2406,6 +2406,14 @@ bool DataRecursiveASTVisitor<Derived>::V
 }
 
 template<typename Derived>
+bool
+DataRecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
+  VisitOMPClauseList(C);
+  TraverseStmt(C->getStep());
+  return true;
+}
+
+template<typename Derived>
 bool DataRecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
   VisitOMPClauseList(C);
   return true;

Modified: cfe/trunk/include/clang/AST/OpenMPClause.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OpenMPClause.h (original)
+++ cfe/trunk/include/clang/AST/OpenMPClause.h Tue Apr 22 08:09:42 2014
@@ -553,6 +553,91 @@ public:
   }
 };
 
+/// \brief This represents clause 'linear' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp simd linear(a,b : 2)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'linear'
+/// with variables 'a', 'b' and linear step '2'.
+///
+class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
+  friend class OMPClauseReader;
+  /// \brief Location of ':'.
+  SourceLocation ColonLoc;
+
+  /// \brief Sets the linear step for clause.
+  void setStep(Expr *Step) { *varlist_end() = Step; }
+
+  /// \brief Build 'linear' clause with given number of variables \a NumVars.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param ColonLoc Location of ':'.
+  /// \param EndLoc Ending location of the clause.
+  /// \param NumVars Number of variables.
+  ///
+  OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+                  SourceLocation ColonLoc, SourceLocation EndLoc,
+                  unsigned NumVars)
+      : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
+                                          EndLoc, NumVars),
+        ColonLoc(ColonLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  /// \param NumVars Number of variables.
+  ///
+  explicit OMPLinearClause(unsigned NumVars)
+      : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
+                                          SourceLocation(), SourceLocation(),
+                                          NumVars),
+        ColonLoc(SourceLocation()) {}
+
+public:
+  /// \brief Creates clause with a list of variables \a VL and a linear step
+  /// \a Step.
+  ///
+  /// \param C AST Context.
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param ColonLoc Location of ':'.
+  /// \param EndLoc Ending location of the clause.
+  /// \param VL List of references to the variables.
+  /// \param Step Linear step.
+  static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc,
+                                 SourceLocation LParenLoc,
+                                 SourceLocation ColonLoc, SourceLocation EndLoc,
+                                 ArrayRef<Expr *> VL, Expr *Step);
+
+  /// \brief Creates an empty clause with the place for \a NumVars variables.
+  ///
+  /// \param C AST context.
+  /// \param NumVars Number of variables.
+  ///
+  static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
+
+  /// \brief Sets the location of ':'.
+  void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+  /// \brief Returns the location of '('.
+  SourceLocation getColonLoc() const { return ColonLoc; }
+
+  /// \brief Returns linear step.
+  Expr *getStep() { return *varlist_end(); }
+  /// \brief Returns linear step.
+  const Expr *getStep() const { return *varlist_end(); }
+
+  StmtRange children() {
+    return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+                     reinterpret_cast<Stmt **>(varlist_end() + 1));
+  }
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_linear;
+  }
+};
+
 /// \brief This represents clause 'copyin' in the '#pragma omp ...' directives.
 ///
 /// \code

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Apr 22 08:09:42 2014
@@ -2443,6 +2443,13 @@ bool RecursiveASTVisitor<Derived>::Visit
 }
 
 template<typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
+  VisitOMPClauseList(C);
+  TraverseStmt(C->getStep());
+  return true;
+}
+
+template<typename Derived>
 bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
   VisitOMPClauseList(C);
   return true;

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Apr 22 08:09:42 2014
@@ -671,6 +671,7 @@ def ASM : DiagGroup<"asm", [
 
 // OpenMP warnings.
 def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
+def OpenMPClauses : DiagGroup<"openmp-clauses">;
 
 // Backend warnings.
 def BackendInlineAsm : DiagGroup<"inline-asm">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 22 08:09:42 2014
@@ -6928,6 +6928,16 @@ def err_omp_ambiguous_conversion : Error
   "enumeration type">;
 def err_omp_required_access : Error<
   "%0 variable must be %1">;
+def err_omp_const_variable : Error<
+  "const-qualified variable cannot be %0">;
+def err_omp_linear_incomplete_type : Error<
+  "a linear variable with incomplete type %0">;
+def err_omp_linear_expected_int_or_ptr : Error<
+  "argument of a linear clause should be of integral or pointer "
+  "type, not %0">;
+def warn_omp_linear_step_zero : Warning<
+  "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">,
+  InGroup<OpenMPClauses>;
 } // 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=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Tue Apr 22 08:09:42 2014
@@ -42,6 +42,7 @@ OPENMP_CLAUSE(default, OMPDefaultClause)
 OPENMP_CLAUSE(private, OMPPrivateClause)
 OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
 OPENMP_CLAUSE(shared,  OMPSharedClause)
+OPENMP_CLAUSE(linear,  OMPLinearClause)
 OPENMP_CLAUSE(copyin,  OMPCopyinClause)
 
 // Clauses allowed for OpenMP directive 'parallel'.
@@ -55,6 +56,7 @@ OPENMP_PARALLEL_CLAUSE(copyin)
 
 // FIXME: more clauses allowed for directive 'omp simd'.
 OPENMP_SIMD_CLAUSE(private)
+OPENMP_SIMD_CLAUSE(linear)
 OPENMP_SIMD_CLAUSE(safelen)
 
 // Static attributes for 'default' clause.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 22 08:09:42 2014
@@ -7286,8 +7286,10 @@ public:
 
   OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
                                       ArrayRef<Expr *> Vars,
+                                      Expr *TailExpr,
                                       SourceLocation StartLoc,
                                       SourceLocation LParenLoc,
+                                      SourceLocation ColonLoc,
                                       SourceLocation EndLoc);
   /// \brief Called on well-formed 'private' clause.
   OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
@@ -7304,6 +7306,13 @@ public:
                                      SourceLocation StartLoc,
                                      SourceLocation LParenLoc,
                                      SourceLocation EndLoc);
+  /// \brief Called on well-formed 'linear' clause.
+  OMPClause *ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList,
+                                     Expr *Step,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation ColonLoc,
+                                     SourceLocation EndLoc);
   /// \brief Called on well-formed 'copyin' clause.
   OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
                                      SourceLocation StartLoc,

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Tue Apr 22 08:09:42 2014
@@ -1192,6 +1192,30 @@ OMPSharedClause *OMPSharedClause::Create
   return new (Mem) OMPSharedClause(N);
 }
 
+OMPLinearClause *OMPLinearClause::Create(const ASTContext &C,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation ColonLoc,
+                                         SourceLocation EndLoc,
+                                         ArrayRef<Expr *> VL, Expr *Step) {
+  void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
+                                                  llvm::alignOf<Expr *>()) +
+                         sizeof(Expr *) * (VL.size() + 1));
+  OMPLinearClause *Clause = new (Mem)
+      OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
+  Clause->setVarRefs(VL);
+  Clause->setStep(Step);
+  return Clause;
+}
+
+OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
+                                              unsigned NumVars) {
+  void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
+                                                  llvm::alignOf<Expr *>()) +
+                         sizeof(Expr *) * (NumVars + 1));
+  return new (Mem) OMPLinearClause(NumVars);
+}
+
 OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
                                          SourceLocation StartLoc,
                                          SourceLocation LParenLoc,

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Apr 22 08:09:42 2014
@@ -664,6 +664,18 @@ void OMPClausePrinter::VisitOMPSharedCla
   }
 }
 
+void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
+  if (!Node->varlist_empty()) {
+    OS << "linear";
+    VisitOMPClauseList(Node, '(');
+    if (Node->getStep() != 0) {
+      OS << ": ";
+      Node->getStep()->printPretty(OS, 0, Policy, 0);
+    }
+    OS << ")";
+  }
+}
+
 void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
   if (!Node->varlist_empty()) {
     OS << "copyin";

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Apr 22 08:09:42 2014
@@ -297,6 +297,10 @@ void OMPClauseProfiler::VisitOMPFirstpri
 void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
   VisitOMPClauseList(C);
 }
+void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
+  VisitOMPClauseList(C);
+  Profiler->VisitStmt(C->getStep());
+}
 void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
   VisitOMPClauseList(C);
 }

Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Tue Apr 22 08:09:42 2014
@@ -83,6 +83,7 @@ unsigned clang::getOpenMPSimpleClauseTyp
   case OMPC_private:
   case OMPC_firstprivate:
   case OMPC_shared:
+  case OMPC_linear:
   case OMPC_copyin:
   case NUM_OPENMP_CLAUSES:
     break;
@@ -110,6 +111,7 @@ const char *clang::getOpenMPSimpleClause
   case OMPC_private:
   case OMPC_firstprivate:
   case OMPC_shared:
+  case OMPC_linear:
   case OMPC_copyin:
   case NUM_OPENMP_CLAUSES:
     break;

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Tue Apr 22 08:09:42 2014
@@ -258,7 +258,7 @@ bool Parser::ParseOpenMPSimpleVarList(Op
 ///
 ///    clause:
 ///       if-clause | num_threads-clause | safelen-clause | default-clause |
-///       private-clause | firstprivate-clause | shared-clause
+///       private-clause | firstprivate-clause | shared-clause | linear-clause
 ///
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                      OpenMPClauseKind CKind, bool FirstClause) {
@@ -301,6 +301,7 @@ OMPClause *Parser::ParseOpenMPClause(Ope
   case OMPC_private:
   case OMPC_firstprivate:
   case OMPC_shared:
+  case OMPC_linear:
   case OMPC_copyin:
     Clause = ParseOpenMPVarListClause(CKind);
     break;
@@ -392,10 +393,13 @@ OMPClause *Parser::ParseOpenMPSimpleClau
 ///       'firstprivate' '(' list ')'
 ///    shared-clause:
 ///       'shared' '(' list ')'
+///    linear-clause:
+///       'linear' '(' list [ ':' linear-step ] ')'
 ///
 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
   SourceLocation Loc = Tok.getLocation();
   SourceLocation LOpen = ConsumeToken();
+  SourceLocation ColonLoc = SourceLocation();
   // Parse '('.
   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
   if (T.expectAndConsume(diag::err_expected_lparen_after,
@@ -404,8 +408,10 @@ OMPClause *Parser::ParseOpenMPVarListCla
 
   SmallVector<Expr *, 5> Vars;
   bool IsComma = true;
-  while (IsComma || (Tok.isNot(tok::r_paren) &&
+  const bool MayHaveTail = (Kind == OMPC_linear);
+  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                      Tok.isNot(tok::annot_pragma_openmp_end))) {
+    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
     // Parse variable
     ExprResult VarExpr = ParseAssignmentExpression();
     if (VarExpr.isUsable()) {
@@ -416,21 +422,34 @@ OMPClause *Parser::ParseOpenMPVarListCla
     }
     // Skip ',' if any
     IsComma = Tok.is(tok::comma);
-    if (IsComma) {
+    if (IsComma)
       ConsumeToken();
-    } else if (Tok.isNot(tok::r_paren) &&
-               Tok.isNot(tok::annot_pragma_openmp_end)) {
-      Diag(Tok, diag::err_omp_expected_punc)
-        << getOpenMPClauseName(Kind);
-    }
+    else if (Tok.isNot(tok::r_paren) &&
+             Tok.isNot(tok::annot_pragma_openmp_end) &&
+             (!MayHaveTail || Tok.isNot(tok::colon)))
+      Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
+  }
+
+  // Parse ':' linear-step
+  Expr *TailExpr = 0;
+  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
+  if (MustHaveTail) {
+    ColonLoc = Tok.getLocation();
+    ConsumeToken();
+    ExprResult Tail = ParseAssignmentExpression();
+    if (Tail.isUsable())
+      TailExpr = Tail.take();
+    else
+      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+                StopBeforeMatch);
   }
 
   // Parse ')'.
   T.consumeClose();
-  if (Vars.empty())
+  if (Vars.empty() || (MustHaveTail && !TailExpr))
     return 0;
 
-  return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
-                                          Tok.getLocation());
+  return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen,
+                                          ColonLoc, Tok.getLocation());
 }
 

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Apr 22 08:09:42 2014
@@ -294,9 +294,10 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
   if (Kind != OMPD_parallel) {
     if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() &&
         (D->getStorageClass() == SC_Auto ||
-         D->getStorageClass() == SC_None))
+         D->getStorageClass() == SC_None)) {
       DVar.CKind = OMPC_private;
       return DVar;
+    }
   }
 
   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -774,6 +775,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprCl
   case OMPC_private:
   case OMPC_firstprivate:
   case OMPC_shared:
+  case OMPC_linear:
   case OMPC_copyin:
   case OMPC_threadprivate:
   case OMPC_unknown:
@@ -929,6 +931,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause
   case OMPC_private:
   case OMPC_firstprivate:
   case OMPC_shared:
+  case OMPC_linear:
   case OMPC_copyin:
   case OMPC_threadprivate:
   case OMPC_unknown:
@@ -986,8 +989,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClaus
 
 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
                                           ArrayRef<Expr *> VarList,
+                                          Expr *TailExpr,
                                           SourceLocation StartLoc,
                                           SourceLocation LParenLoc,
+                                          SourceLocation ColonLoc,
                                           SourceLocation EndLoc) {
   OMPClause *Res = 0;
   switch (Kind) {
@@ -1000,6 +1005,10 @@ OMPClause *Sema::ActOnOpenMPVarListClaus
   case OMPC_shared:
     Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
     break;
+  case OMPC_linear:
+    Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
+                                  ColonLoc, EndLoc);
+    break;
   case OMPC_copyin:
     Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
     break;
@@ -1382,6 +1391,135 @@ OMPClause *Sema::ActOnOpenMPSharedClause
   return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
 }
 
+OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation ColonLoc,
+                                         SourceLocation EndLoc) {
+  SmallVector<Expr *, 8> Vars;
+  for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
+       I != E; ++I) {
+    assert(*I && "NULL expr in OpenMP linear clause.");
+    if (isa<DependentScopeDeclRefExpr>(*I)) {
+      // It will be analyzed later.
+      Vars.push_back(*I);
+      continue;
+    }
+
+    // OpenMP [2.14.3.7, linear clause]
+    // A list item that appears in a linear clause is subject to the private
+    // clause semantics described in Section 2.14.3.3 on page 159 except as
+    // noted. In addition, the value of the new list item on each iteration
+    // of the associated loop(s) corresponds to the value of the original
+    // list item before entering the construct plus the logical number of
+    // the iteration times linear-step.
+
+    SourceLocation ELoc = (*I)->getExprLoc();
+    // OpenMP [2.1, C/C++]
+    //  A list item is a variable name.
+    // 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.
+    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
+    if (!DE || !isa<VarDecl>(DE->getDecl())) {
+      Diag(ELoc, diag::err_omp_expected_var_name) << (*I)->getSourceRange();
+      continue;
+    }
+
+    VarDecl *VD = cast<VarDecl>(DE->getDecl());
+
+    // OpenMP [2.14.3.7, linear clause]
+    //  A list-item cannot appear in more than one linear clause.
+    //  A list-item that appears in a linear clause cannot appear in any
+    //  other data-sharing attribute clause.
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    if (DVar.RefExpr) {
+      Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
+                                          << getOpenMPClauseName(OMPC_linear);
+      Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+          << getOpenMPClauseName(DVar.CKind);
+      continue;
+    }
+
+    QualType QType = VD->getType();
+    if (QType->isDependentType() || QType->isInstantiationDependentType()) {
+      // It will be analyzed later.
+      Vars.push_back(DE);
+      continue;
+    }
+
+    // A variable must not have an incomplete type or a reference type.
+    if (RequireCompleteType(ELoc, QType,
+                            diag::err_omp_linear_incomplete_type)) {
+      continue;
+    }
+    if (QType->isReferenceType()) {
+      Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+          << getOpenMPClauseName(OMPC_linear) << QType;
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+
+    // A list item must not be const-qualified.
+    if (QType.isConstant(Context)) {
+      Diag(ELoc, diag::err_omp_const_variable)
+          << getOpenMPClauseName(OMPC_linear);
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+
+    // A list item must be of integral or pointer type.
+    QType = QType.getUnqualifiedType().getCanonicalType();
+    const Type *Ty = QType.getTypePtrOrNull();
+    if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
+                !Ty->isPointerType())) {
+      Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType;
+      bool IsDecl =
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << VD;
+      continue;
+    }
+
+    DSAStack->addDSA(VD, DE, OMPC_linear);
+    Vars.push_back(DE);
+  }
+
+  if (Vars.empty())
+    return 0;
+
+  Expr *StepExpr = Step;
+  if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
+      !Step->isInstantiationDependent() &&
+      !Step->containsUnexpandedParameterPack()) {
+    SourceLocation StepLoc = Step->getLocStart();
+    ExprResult Val = PerformImplicitIntegerConversion(StepLoc, Step);
+    if (Val.isInvalid())
+      return 0;
+    StepExpr = Val.take();
+
+    // Warn about zero linear step (it would be probably better specified as
+    // making corresponding variables 'const').
+    llvm::APSInt Result;
+    if (StepExpr->isIntegerConstantExpr(Result, Context) &&
+        !Result.isNegative() && !Result.isStrictlyPositive())
+      Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0]
+                                                     << (Vars.size() > 1);
+  }
+
+  return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
+                                 Vars, StepExpr);
+}
+
 OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
                                          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=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Apr 22 08:09:42 2014
@@ -1382,6 +1382,19 @@ public:
                                              EndLoc);
   }
 
+  /// \brief Build a new OpenMP 'linear' clause.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+                                    SourceLocation StartLoc,
+                                    SourceLocation LParenLoc,
+                                    SourceLocation ColonLoc,
+                                    SourceLocation EndLoc) {
+    return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc,
+                                             ColonLoc, EndLoc);
+  }
+
   /// \brief Build a new OpenMP 'copyin' clause.
   ///
   /// By default, performs semantic analysis to build the new statement.
@@ -6435,6 +6448,25 @@ TreeTransform<Derived>::TransformOMPShar
 }
 
 template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *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 0;
+    Vars.push_back(EVar.take());
+  }
+  ExprResult Step = getDerived().TransformExpr(C->getStep());
+  if (Step.isInvalid())
+    return 0;
+  return getDerived().RebuildOMPLinearClause(
+      Vars, Step.take(), C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
+      C->getLocEnd());
+}
+
+template<typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
   llvm::SmallVector<Expr *, 16> Vars;

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Apr 22 08:09:42 2014
@@ -1692,6 +1692,9 @@ OMPClause *OMPClauseReader::readClause()
   case OMPC_shared:
     C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
     break;
+  case OMPC_linear:
+    C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]);
+    break;
   case OMPC_copyin:
     C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
     break;
@@ -1755,6 +1758,18 @@ void OMPClauseReader::VisitOMPSharedClau
   C->setVarRefs(Vars);
 }
 
+void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
+  C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+  C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+  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);
+  C->setStep(Reader->Reader.ReadSubExpr());
+}
+
 void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
   C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
   unsigned NumVars = C->varlist_size();

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Apr 22 08:09:42 2014
@@ -1716,6 +1716,15 @@ void OMPClauseWriter::VisitOMPSharedClau
     Writer->Writer.AddStmt(VE);
 }
 
+void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
+  Record.push_back(C->varlist_size());
+  Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+  Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+  for (auto *VE : C->varlists())
+    Writer->Writer.AddStmt(VE);
+  Writer->Writer.AddStmt(C->getStep());
+}
+
 void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
   Record.push_back(C->varlist_size());
   Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);

Modified: cfe/trunk/test/OpenMP/simd_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_ast_print.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/simd_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/simd_ast_print.cpp Tue Apr 22 08:09:42 2014
@@ -14,8 +14,8 @@ template<class T, class N> T reduct(T* a
   N myind;
   T sum = (T)0;
 // CHECK: T sum = (T)0;
-#pragma omp simd private(myind, g_ind)
-// CHECK-NEXT: #pragma omp simd private(myind,g_ind)
+#pragma omp simd private(myind, g_ind), linear(ind)
+// CHECK-NEXT: #pragma omp simd private(myind,g_ind) linear(ind)
   for (i = 0; i < num; ++i) {
     myind = ind;
     T cur = arr[myind];
@@ -31,13 +31,16 @@ template<class T> struct S {
   T result(T *v) const {
     T res;
     T val;
+    T lin = 0;
 // CHECK: T res;
 // CHECK: T val;
-    #pragma omp simd private(val)  safelen(7)
-// CHECK-NEXT: #pragma omp simd private(val) safelen(7)
+// CHECK: T lin = 0;
+    #pragma omp simd private(val)  safelen(7) linear(lin : -5)
+// CHECK-NEXT: #pragma omp simd private(val) safelen(7) linear(lin: -5)
     for (T i = 7; i < m_a; ++i) {
       val = v[i-7] + m_a;
       res = val;
+      lin -= 5;
     }
     const T clen = 3;
 // CHECK: T clen = 3;
@@ -58,9 +61,14 @@ template<class T> struct S {
 
 template<int LEN> struct S2 {
   static void func(int n, float *a, float *b, float *c) {
-#pragma omp simd safelen(LEN)
+    int k1 = 0, k2 = 0;
+#pragma omp simd safelen(LEN) linear(k1,k2:LEN)
     for(int i = 0; i < n; i++) {
       c[i] = a[i] + b[i];
+      c[k1] = a[k1] + b[k1];
+      c[k2] = a[k2] + b[k2];
+      k1 = k1 + LEN;
+      k2 = k2 + LEN;
     }
   }
 };
@@ -68,9 +76,14 @@ template<int LEN> struct S2 {
 // S2<4>::func is called below in main.
 // CHECK: template <int LEN = 4> struct S2 {
 // CHECK-NEXT: static void func(int n, float *a, float *b, float *c)     {
-// CHECK-NEXT: #pragma omp simd safelen(4)
+// CHECK-NEXT:   int k1 = 0, k2 = 0;
+// CHECK-NEXT: #pragma omp simd safelen(4) linear(k1,k2: 4)
 // CHECK-NEXT:   for (int i = 0; i < n; i++) {
 // CHECK-NEXT:     c[i] = a[i] + b[i];
+// CHECK-NEXT:     c[k1] = a[k1] + b[k1];
+// CHECK-NEXT:     c[k2] = a[k2] + b[k2];
+// CHECK-NEXT:     k1 = k1 + 4;
+// CHECK-NEXT:     k2 = k2 + 4;
 // CHECK-NEXT:   }
 // CHECK-NEXT: }
 
@@ -99,8 +112,8 @@ int main (int argc, char **argv) {
 // CHECK-NEXT: foo();
   const int CLEN = 4;
 // CHECK-NEXT: const int CLEN = 4;
-  #pragma omp simd safelen(CLEN)
-// CHECK-NEXT: #pragma omp simd safelen(CLEN)
+  #pragma omp simd linear(a:CLEN) safelen(CLEN)
+// CHECK-NEXT: #pragma omp simd linear(a: CLEN) safelen(CLEN)
   for (int i = 0; i < 10; ++i)foo();
 // CHECK-NEXT: for (int i = 0; i < 10; ++i)
 // CHECK-NEXT: foo();

Added: cfe/trunk/test/OpenMP/simd_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_linear_messages.cpp?rev=206891&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/simd_linear_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/simd_linear_messages.cpp Tue Apr 22 08:09:42 2014
@@ -0,0 +1,205 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s
+
+namespace X {
+  int x;
+};
+
+struct B {
+  static int ib; // expected-note {{'B::ib' declared here}}
+  static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons()
+{
+  int B = 0;
+  #pragma omp simd linear(B:bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{unexpected ':' in nested name specifier; did you mean '::'}}
+  #pragma omp simd linear(B::ib:B:bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+  #pragma omp simd linear(B:ib)
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{unexpected ':' in nested name specifier; did you mean '::'?}}
+  #pragma omp simd linear(z:B:ib)
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp simd linear(B:B::bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp simd linear(X::x : ::z)
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp simd linear(B,::z, X::x)
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp simd linear(::z)
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{expected variable name}}
+  #pragma omp simd linear(B::bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp simd linear(B::ib,B:C1+C2)
+  for (int i = 0; i < 10; ++i) ;
+}
+
+template<int L, class T, class N> T test_template(T* arr, N num) {
+  N i;
+  T sum = (T)0;
+  T ind2 = - num * L; // expected-note {{'ind2' defined here}}
+  // 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];
+    ind2 += L;
+    sum += cur;
+  }
+}
+
+template<int LEN> int test_warn() {
+  int ind2 = 0;
+  // expected-warning at +1 {{zero linear step (ind2 should probably be const)}}
+  #pragma omp simd linear(ind2:LEN)
+  for (int i = 0; i < 100; i++) {
+    ind2 += LEN;
+  }
+  return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+  mutable int a;
+public:
+  S2():a(0) { }
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+  int a;
+public:
+  S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+  int a;
+  S4();
+public:
+  S4(int v):a(v) { }
+};
+class S5 {
+  int a;
+  S5():a(0) {}
+public:
+  S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template<class I, class C> int foomain(I argc, C **argv) {
+  I e(4);
+  I g(5);
+  int i;
+  int &j = i; // expected-note {{'j' defined here}}
+  #pragma omp simd linear // expected-error {{expected '(' after 'linear'}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear () // expected-error {{expected expression}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc : 5)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}}
+  for (int k = 0; k < argc; ++k) ++k;
+  // expected-error at +2 {{linear variable with incomplete type 'S1'}}
+  // expected-error at +1 {{const-qualified variable cannot be linear}}
+  #pragma omp simd linear (a, b:B::ib)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear(e, g)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear(i)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp parallel
+  {
+    int v = 0;
+    int i;
+    #pragma omp simd linear(v:i)
+    for (int k = 0; k < argc; ++k) { i = k; v += i; }
+  }
+  #pragma omp simd linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type}}
+  for (int k = 0; k < argc; ++k) ++k;
+  int v = 0;
+  #pragma omp simd linear(v:j)
+  for (int k = 0; k < argc; ++k) { ++k; v += j; }
+  #pragma omp simd linear(i)
+  for (int k = 0; k < argc; ++k) ++k;
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  double darr[100];
+  // expected-note at +1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+  test_template<-4>(darr, 4);
+  // expected-note at +1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+  test_warn<0>();
+
+  S4 e(4); // expected-note {{'e' defined here}}
+  S5 g(5); // expected-note {{'g' defined here}}
+  int i;
+  int &j = i; // expected-note {{'j' defined here}}
+  #pragma omp simd linear // expected-error {{expected '(' after 'linear'}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear () // expected-error {{expected expression}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argc)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}}
+  for (int k = 0; k < argc; ++k) ++k;
+  // expected-error at +2 {{linear variable with incomplete type 'S1'}}
+  // expected-error at +1 {{const-qualified variable cannot be linear}}
+  #pragma omp simd linear (a, b) 
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  // expected-error at +2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
+  // expected-error at +1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+  #pragma omp simd linear(e, g)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp simd linear(i)
+    for (int k = 0; k < argc; ++k) ++k;
+    #pragma omp simd linear(i : 4)
+    for (int k = 0; k < argc; ++k) { ++k; i += 4; }
+  }
+  #pragma omp simd linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type 'int &'}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear(i)
+  for (int k = 0; k < argc; ++k) ++k;
+
+  foomain<int,char>(argc,argv);
+  return 0;
+}
+

Modified: cfe/trunk/test/OpenMP/simd_misc_messages.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_misc_messages.c?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/simd_misc_messages.c (original)
+++ cfe/trunk/test/OpenMP/simd_misc_messages.c Tue Apr 22 08:09:42 2014
@@ -146,6 +146,80 @@ void test_safelen()
   for (i = 0; i < 16; ++i);
 }
 
+void test_linear()
+{
+  int i;
+  // expected-error at +1 {{expected expression}} expected-error at +1 {{expected ')'}} expected-note at +1 {{to match this '('}}
+  #pragma omp simd linear(
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +2 {{expected expression}}
+  // expected-error at +1 {{expected expression}} expected-error at +1 {{expected ')'}} expected-note at +1 {{to match this '('}}
+  #pragma omp simd linear(,
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +2 {{expected expression}}
+  // expected-error at +1 {{expected expression}}
+  #pragma omp simd linear(,)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{expected expression}}
+  #pragma omp simd linear()
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{expected expression}}
+  #pragma omp simd linear(int)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{expected variable name}}
+  #pragma omp simd linear(0)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{use of undeclared identifier 'x'}}
+  #pragma omp simd linear(x)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +2 {{use of undeclared identifier 'x'}}
+  // expected-error at +1 {{use of undeclared identifier 'y'}}
+  #pragma omp simd linear(x, y)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +3 {{use of undeclared identifier 'x'}}
+  // expected-error at +2 {{use of undeclared identifier 'y'}}
+  // expected-error at +1 {{use of undeclared identifier 'z'}}
+  #pragma omp simd linear(x, y, z)
+  for (i = 0; i < 16; ++i) ;
+
+  int x, y;
+  // expected-error at +1 {{expected expression}}
+  #pragma omp simd linear(x:)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{expected expression}} expected-error at +1 {{expected ')'}} expected-note at +1 {{to match this '('}}
+  #pragma omp simd linear(x:,)
+  for (i = 0; i < 16; ++i) ;
+  #pragma omp simd linear(x:1)
+  for (i = 0; i < 16; ++i) ;
+  #pragma omp simd linear(x:2*2)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{expected ')'}} expected-note at +1 {{to match this '('}}
+  #pragma omp simd linear(x:1,y)
+  for (i = 0; i < 16; ++i) ;
+  // expected-error at +1 {{expected ')'}} expected-note at +1 {{to match this '('}}
+  #pragma omp simd linear(x:1,y,z:1)
+  for (i = 0; i < 16; ++i) ;
+
+  // expected-note at +2 {{defined as linear}}
+  // expected-error at +1 {{linear variable cannot be linear}}
+  #pragma omp simd linear(x) linear(x)
+  for (i = 0; i < 16; ++i) ;
+
+  // expected-note at +2 {{defined as private}}
+  // expected-error at +1 {{private variable cannot be linear}}
+  #pragma omp simd private(x) linear(x)
+  for (i = 0; i < 16; ++i) ;
+
+  // expected-note at +2 {{defined as linear}}
+  // expected-error at +1 {{linear variable cannot be private}}
+  #pragma omp simd linear(x) private(x)
+  for (i = 0; i < 16; ++i) ;
+
+  // expected-warning at +1 {{zero linear step (x and other variables in clause should probably be const)}}
+  #pragma omp simd linear(x,y:0)
+  for (i = 0; i < 16; ++i) ;
+}
+
 void test_private()
 {
   int i;

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=206891&r1=206890&r2=206891&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Apr 22 08:09:42 2014
@@ -1954,6 +1954,10 @@ void OMPClauseEnqueue::VisitOMPFirstpriv
 void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
   VisitOMPClauseList(C);
 }
+void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
+  VisitOMPClauseList(C);
+  Visitor->AddStmt(C->getStep());
+}
 void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
   VisitOMPClauseList(C);
 }





More information about the cfe-commits mailing list