<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 31, 2015 at 9:48 AM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@gmail.com" target="_blank">benny.kra@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Mon, Aug 31, 2015 at 5:12 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Any chance this would be improved/further simplified by basing it on the adapter_iterator helper in LLVM's STL Utilities?</div></blockquote><div><br></div></span><div>Fair enough, r246452. I was a bit nervous because this iterator overrides operator++ but iterator_adaptor_base seems to be doing the right thing even when ++ is overridden.</div></div></div></div></blockquote><div><br>Neat - thanks a bunch! :D<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>- Ben</div><div><div class="h5">







<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div><div class="gmail_extra"><div class="gmail_quote">On Sun, Aug 30, 2015 at 8:12 AM, Benjamin Kramer via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: d0k<br>
Date: Sun Aug 30 10:12:28 2015<br>
New Revision: 246384<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=246384&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=246384&view=rev</a><br>
Log:<br>
[OpenMP] Make the filetered clause iterator a real iterator and type safe.<br>
<br>
This replaces the filtered generic iterator with a type-specfic one based<br>
on dyn_cast instead of comparing the kind enum. This allows us to use<br>
range-based for loops and eliminates casts. No functionality change<br>
intended.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/StmtOpenMP.h<br>
    cfe/trunk/lib/AST/Stmt.cpp<br>
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp<br>
    cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/StmtOpenMP.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=246384&r1=246383&r2=246384&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=246384&r1=246383&r2=246384&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/StmtOpenMP.h (original)<br>
+++ cfe/trunk/include/clang/AST/StmtOpenMP.h Sun Aug 30 10:12:28 2015<br>
@@ -92,65 +92,91 @@ public:<br>
   /// \brief Iterates over a filtered subrange of clauses applied to a<br>
   /// directive.<br>
   ///<br>
-  /// This iterator visits only those declarations that meet some run-time<br>
-  /// criteria.<br>
-  template <class FilterPredicate> class filtered_clause_iterator {<br>
-  protected:<br>
+  /// This iterator visits only clauses of type SpecificClause.<br>
+  template <typename SpecificClause><br>
+  class specific_clause_iterator<br>
+      : public std::iterator<std::forward_iterator_tag, const SpecificClause *,<br>
+                             ptrdiff_t, const SpecificClause *,<br>
+                             const SpecificClause *> {<br>
     ArrayRef<OMPClause *>::const_iterator Current;<br>
     ArrayRef<OMPClause *>::const_iterator End;<br>
-    FilterPredicate Pred;<br>
+<br>
     void SkipToNextClause() {<br>
-      while (Current != End && !Pred(*Current))<br>
+      while (Current != End && !isa<SpecificClause>(*Current))<br>
         ++Current;<br>
     }<br>
<br>
   public:<br>
-    typedef const OMPClause *value_type;<br>
-    filtered_clause_iterator() : Current(), End() {}<br>
-    filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred)<br>
-        : Current(Arr.begin()), End(Arr.end()), Pred(std::move(Pred)) {<br>
+    explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)<br>
+        : Current(Clauses.begin()), End(Clauses.end()) {<br>
       SkipToNextClause();<br>
     }<br>
-    value_type operator*() const { return *Current; }<br>
-    value_type operator->() const { return *Current; }<br>
-    filtered_clause_iterator &operator++() {<br>
+<br>
+    const SpecificClause *operator*() const {<br>
+      return cast<SpecificClause>(*Current);<br>
+    }<br>
+    const SpecificClause *operator->() const {<br>
+      return cast<SpecificClause>(*Current);<br>
+    }<br>
+<br>
+    specific_clause_iterator &operator++() {<br>
       ++Current;<br>
       SkipToNextClause();<br>
       return *this;<br>
     }<br>
-<br>
-    filtered_clause_iterator operator++(int) {<br>
-      filtered_clause_iterator tmp(*this);<br>
+    specific_clause_iterator operator++(int) {<br>
+      specific_clause_iterator tmp(*this);<br>
       ++(*this);<br>
       return tmp;<br>
     }<br>
<br>
-    bool operator!() { return Current == End; }<br>
-    explicit operator bool() { return Current != End; }<br>
-    bool empty() const { return Current == End; }<br>
+    bool operator==(const specific_clause_iterator &RHS) const {<br>
+      assert(End == RHS.End && "Comparing iterators of different directives!");<br>
+      return Current == RHS.Current;<br>
+    }<br>
+    bool operator!=(const specific_clause_iterator &RHS) const {<br>
+      return !(*this == RHS);<br>
+    }<br>
   };<br>
<br>
-  template <typename Fn><br>
-  filtered_clause_iterator<Fn> getFilteredClauses(Fn &&fn) const {<br>
-    return filtered_clause_iterator<Fn>(clauses(), std::move(fn));<br>
+  template <typename SpecificClause><br>
+  static llvm::iterator_range<specific_clause_iterator<SpecificClause>><br>
+  getClausesOfKind(ArrayRef<OMPClause *> Clauses) {<br>
+    return {specific_clause_iterator<SpecificClause>(Clauses),<br>
+            specific_clause_iterator<SpecificClause>(<br>
+                llvm::makeArrayRef(Clauses.end(), 0))};<br>
   }<br>
-  struct ClauseKindFilter {<br>
-    OpenMPClauseKind Kind;<br>
-    bool operator()(const OMPClause *clause) const {<br>
-      return clause->getClauseKind() == Kind;<br>
-    }<br>
-  };<br>
-  filtered_clause_iterator<ClauseKindFilter><br>
-  getClausesOfKind(OpenMPClauseKind Kind) const {<br>
-    return getFilteredClauses(ClauseKindFilter{Kind});<br>
+<br>
+  template <typename SpecificClause><br>
+  llvm::iterator_range<specific_clause_iterator<SpecificClause>><br>
+  getClausesOfKind() const {<br>
+    return getClausesOfKind<SpecificClause>(clauses());<br>
   }<br>
<br>
-  /// \brief Gets a single clause of the specified kind \a K associated with the<br>
+  /// Gets a single clause of the specified kind associated with the<br>
   /// current directive iff there is only one clause of this kind (and assertion<br>
   /// is fired if there is more than one clause is associated with the<br>
-  /// directive). Returns nullptr if no clause of kind \a K is associated with<br>
+  /// directive). Returns nullptr if no clause of this kind is associated with<br>
   /// the directive.<br>
-  const OMPClause *getSingleClause(OpenMPClauseKind K) const;<br>
+  template <typename SpecificClause><br>
+  const SpecificClause *getSingleClause() const {<br>
+    auto Clauses = getClausesOfKind<SpecificClause>();<br>
+<br>
+    if (Clauses.begin() != Clauses.end()) {<br>
+      assert(std::next(Clauses.begin()) == Clauses.end() &&<br>
+             "There are at least 2 clauses of the specified kind");<br>
+      return *Clauses.begin();<br>
+    }<br>
+    return nullptr;<br>
+  }<br>
+<br>
+  /// Returns true if the current directive has one or more clauses of a<br>
+  /// specific kind.<br>
+  template <typename SpecificClause><br>
+  bool hasClausesOfKind() const {<br>
+    auto Clauses = getClausesOfKind<SpecificClause>();<br>
+    return Clauses.begin() != Clauses.end();<br>
+  }<br>
<br>
   /// \brief Returns starting location of directive kind.<br>
   SourceLocation getLocStart() const { return StartLoc; }<br>
<br>
Modified: cfe/trunk/lib/AST/Stmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=246384&r1=246383&r2=246384&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=246384&r1=246383&r2=246384&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Stmt.cpp (original)<br>
+++ cfe/trunk/lib/AST/Stmt.cpp Sun Aug 30 10:12:28 2015<br>
@@ -1621,18 +1621,6 @@ OMPDependClause *OMPDependClause::Create<br>
   return new (Mem) OMPDependClause(N);<br>
 }<br>
<br>
-const OMPClause *<br>
-OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const {<br>
-  auto &&I = getClausesOfKind(K);<br>
-<br>
-  if (I) {<br>
-    auto *Clause = *I;<br>
-    assert(!++I && "There are at least 2 clauses of the specified kind");<br>
-    return Clause;<br>
-  }<br>
-  return nullptr;<br>
-}<br>
-<br>
 OMPParallelDirective *OMPParallelDirective::Create(<br>
                                               const ASTContext &C,<br>
                                               SourceLocation StartLoc,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=246384&r1=246383&r2=246384&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=246384&r1=246383&r2=246384&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Sun Aug 30 10:12:28 2015<br>
@@ -115,8 +115,7 @@ void CodeGenFunction::EmitOMPCopy(CodeGe<br>
 bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,<br>
                                                 OMPPrivateScope &PrivateScope) {<br>
   llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_firstprivate); I; ++I) {<br>
-    auto *C = cast<OMPFirstprivateClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {<br>
     auto IRef = C->varlist_begin();<br>
     auto InitsRef = C->inits().begin();<br>
     for (auto IInit : C->private_copies()) {<br>
@@ -189,8 +188,7 @@ void CodeGenFunction::EmitOMPPrivateClau<br>
     const OMPExecutableDirective &D,<br>
     CodeGenFunction::OMPPrivateScope &PrivateScope) {<br>
   llvm::DenseSet<const VarDecl *> EmittedAsPrivate;<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_private); I; ++I) {<br>
-    auto *C = cast<OMPPrivateClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {<br>
     auto IRef = C->varlist_begin();<br>
     for (auto IInit : C->private_copies()) {<br>
       auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());<br>
@@ -218,8 +216,7 @@ bool CodeGenFunction::EmitOMPCopyinClaus<br>
   // __kmpc_barrier(&loc, global_tid);<br>
   llvm::DenseSet<const VarDecl *> CopiedVars;<br>
   llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_copyin); I; ++I) {<br>
-    auto *C = cast<OMPCopyinClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) {<br>
     auto IRef = C->varlist_begin();<br>
     auto ISrcRef = C->source_exprs().begin();<br>
     auto IDestRef = C->destination_exprs().begin();<br>
@@ -279,9 +276,8 @@ bool CodeGenFunction::EmitOMPLastprivate<br>
     const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {<br>
   bool HasAtLeastOneLastprivate = false;<br>
   llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_lastprivate); I; ++I) {<br>
+  for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {<br>
     HasAtLeastOneLastprivate = true;<br>
-    auto *C = cast<OMPLastprivateClause>(*I);<br>
     auto IRef = C->varlist_begin();<br>
     auto IDestRef = C->destination_exprs().begin();<br>
     for (auto *IInit : C->private_copies()) {<br>
@@ -359,8 +355,7 @@ void CodeGenFunction::EmitOMPLastprivate<br>
   {<br>
     llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;<br>
     bool FirstLCV = true;<br>
-    for (auto &&I = D.getClausesOfKind(OMPC_lastprivate); I; ++I) {<br>
-      auto *C = cast<OMPLastprivateClause>(*I);<br>
+    for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {<br>
       auto IRef = C->varlist_begin();<br>
       auto ISrcRef = C->source_exprs().begin();<br>
       auto IDestRef = C->destination_exprs().begin();<br>
@@ -405,8 +400,7 @@ void CodeGenFunction::EmitOMPLastprivate<br>
 void CodeGenFunction::EmitOMPReductionClauseInit(<br>
     const OMPExecutableDirective &D,<br>
     CodeGenFunction::OMPPrivateScope &PrivateScope) {<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_reduction); I; ++I) {<br>
-    auto *C = cast<OMPReductionClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {<br>
     auto ILHS = C->lhs_exprs().begin();<br>
     auto IRHS = C->rhs_exprs().begin();<br>
     for (auto IRef : C->varlists()) {<br>
@@ -442,9 +436,8 @@ void CodeGenFunction::EmitOMPReductionCl<br>
   llvm::SmallVector<const Expr *, 8> RHSExprs;<br>
   llvm::SmallVector<const Expr *, 8> ReductionOps;<br>
   bool HasAtLeastOneReduction = false;<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_reduction); I; ++I) {<br>
+  for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {<br>
     HasAtLeastOneReduction = true;<br>
-    auto *C = cast<OMPReductionClause>(*I);<br>
     LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());<br>
     RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());<br>
     ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());<br>
@@ -454,7 +447,7 @@ void CodeGenFunction::EmitOMPReductionCl<br>
     // parallel directive (it always has implicit barrier).<br>
     CGM.getOpenMPRuntime().emitReduction(<br>
         *this, D.getLocEnd(), LHSExprs, RHSExprs, ReductionOps,<br>
-        D.getSingleClause(OMPC_nowait) ||<br>
+        D.getSingleClause<OMPNowaitClause>() ||<br>
             isOpenMPParallelDirective(D.getDirectiveKind()) ||<br>
             D.getDirectiveKind() == OMPD_simd,<br>
         D.getDirectiveKind() == OMPD_simd);<br>
@@ -469,23 +462,21 @@ static void emitCommonOMPParallelDirecti<br>
   auto CapturedStruct = CGF.GenerateCapturedStmtArgument(*CS);<br>
   auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(<br>
       S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);<br>
-  if (auto C = S.getSingleClause(OMPC_num_threads)) {<br>
+  if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {<br>
     CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);<br>
-    auto NumThreadsClause = cast<OMPNumThreadsClause>(C);<br>
     auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),<br>
                                          /*IgnoreResultAssign*/ true);<br>
     CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(<br>
         CGF, NumThreads, NumThreadsClause->getLocStart());<br>
   }<br>
-  if (auto *C = S.getSingleClause(OMPC_proc_bind)) {<br>
+  if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {<br>
     CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);<br>
-    auto *ProcBindClause = cast<OMPProcBindClause>(C);<br>
     CGF.CGM.getOpenMPRuntime().emitProcBindClause(<br>
         CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getLocStart());<br>
   }<br>
   const Expr *IfCond = nullptr;<br>
-  if (auto C = S.getSingleClause(OMPC_if)) {<br>
-    IfCond = cast<OMPIfClause>(C)->getCondition();<br>
+  if (const auto *C = S.getSingleClause<OMPIfClause>()) {<br>
+    IfCond = C->getCondition();<br>
   }<br>
   CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn,<br>
                                               CapturedStruct, IfCond);<br>
@@ -526,8 +517,7 @@ void CodeGenFunction::EmitOMPLoopBody(co<br>
     EmitIgnoredExpr(I);<br>
   }<br>
   // Update the linear variables.<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {<br>
-    auto *C = cast<OMPLinearClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {<br>
     for (auto U : C->updates()) {<br>
       EmitIgnoredExpr(U);<br>
     }<br>
@@ -596,8 +586,7 @@ void CodeGenFunction::EmitOMPInnerLoop(<br>
<br>
 void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {<br>
   // Emit inits for the linear variables.<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {<br>
-    auto *C = cast<OMPLinearClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {<br>
     for (auto Init : C->inits()) {<br>
       auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());<br>
       auto *OrigVD = cast<VarDecl>(<br>
@@ -627,8 +616,7 @@ void CodeGenFunction::EmitOMPLinearClaus<br>
 static void emitLinearClauseFinal(CodeGenFunction &CGF,<br>
                                   const OMPLoopDirective &D) {<br>
   // Emit the final values of the linear variables.<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {<br>
-    auto *C = cast<OMPLinearClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {<br>
     auto IC = C->varlist_begin();<br>
     for (auto F : C->finals()) {<br>
       auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());<br>
@@ -648,8 +636,7 @@ static void emitLinearClauseFinal(CodeGe<br>
<br>
 static void emitAlignedClause(CodeGenFunction &CGF,<br>
                               const OMPExecutableDirective &D) {<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_aligned); I; ++I) {<br>
-    auto *Clause = cast<OMPAlignedClause>(*I);<br>
+  for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {<br>
     unsigned ClauseAlignment = 0;<br>
     if (auto AlignmentExpr = Clause->getAlignment()) {<br>
       auto AlignmentCI =<br>
@@ -719,8 +706,7 @@ static void emitPreCond(CodeGenFunction<br>
 static void<br>
 emitPrivateLinearVars(CodeGenFunction &CGF, const OMPExecutableDirective &D,<br>
                       CodeGenFunction::OMPPrivateScope &PrivateScope) {<br>
-  for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {<br>
-    auto *C = cast<OMPLinearClause>(*I);<br>
+  for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {<br>
     auto CurPrivate = C->privates().begin();<br>
     for (auto *E : C->varlists()) {<br>
       auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());<br>
@@ -741,8 +727,7 @@ emitPrivateLinearVars(CodeGenFunction &C<br>
<br>
 static void emitSimdlenSafelenClause(CodeGenFunction &CGF,<br>
                                      const OMPExecutableDirective &D) {<br>
-  if (auto *C =<br>
-          cast_or_null<OMPSimdlenClause>(D.getSingleClause(OMPC_simdlen))) {<br>
+  if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {<br>
     RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),<br>
                                  /*ignoreResult=*/true);<br>
     llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());<br>
@@ -750,9 +735,8 @@ static void emitSimdlenSafelenClause(Cod<br>
     // In presence of finite 'safelen', it may be unsafe to mark all<br>
     // the memory instructions parallel, because loop-carried<br>
     // dependences of 'safelen' iterations are possible.<br>
-    CGF.LoopStack.setParallel(!D.getSingleClause(OMPC_safelen));<br>
-  } else if (auto *C = cast_or_null<OMPSafelenClause>(<br>
-                 D.getSingleClause(OMPC_safelen))) {<br>
+    CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());<br>
+  } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {<br>
     RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),<br>
                                  /*ignoreResult=*/true);<br>
     llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());<br>
@@ -1041,8 +1025,7 @@ emitScheduleClause(CodeGenFunction &CGF,<br>
   // Detect the loop schedule kind and chunk.<br>
   auto ScheduleKind = OMPC_SCHEDULE_unknown;<br>
   llvm::Value *Chunk = nullptr;<br>
-  if (auto *C =<br>
-          cast_or_null<OMPScheduleClause>(S.getSingleClause(OMPC_schedule))) {<br>
+  if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {<br>
     ScheduleKind = C->getScheduleKind();<br>
     if (const auto *Ch = C->getChunkSize()) {<br>
       if (auto *ImpRef = cast_or_null<DeclRefExpr>(C->getHelperChunkSize())) {<br>
@@ -1143,7 +1126,7 @@ bool CodeGenFunction::EmitOMPWorksharing<br>
       ScheduleKind = ScheduleInfo.second;<br>
       const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());<br>
       const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();<br>
-      const bool Ordered = S.getSingleClause(OMPC_ordered) != nullptr;<br>
+      const bool Ordered = S.getSingleClause<OMPOrderedClause>() != nullptr;<br>
       if (RT.isStaticNonchunked(ScheduleKind,<br>
                                 /* Chunked */ Chunk != nullptr) &&<br>
           !Ordered) {<br>
@@ -1208,7 +1191,7 @@ void CodeGenFunction::EmitOMPForDirectiv<br>
   CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen);<br>
<br>
   // Emit an implicit barrier at the end.<br>
-  if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {<br>
+  if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {<br>
     CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);<br>
   }<br>
 }<br>
@@ -1222,7 +1205,7 @@ void CodeGenFunction::EmitOMPForSimdDire<br>
   CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);<br>
<br>
   // Emit an implicit barrier at the end.<br>
-  if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {<br>
+  if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {<br>
     CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);<br>
   }<br>
 }<br>
@@ -1338,7 +1321,7 @@ CodeGenFunction::EmitSections(const OMPE<br>
     // Emit barrier for lastprivates only if 'sections' directive has 'nowait'<br>
     // clause. Otherwise the barrier will be generated by the codegen for the<br>
     // directive.<br>
-    if (HasLastprivates && S.getSingleClause(OMPC_nowait)) {<br>
+    if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {<br>
       // Emit implicit barrier to synchronize threads and avoid data races on<br>
       // initialization of firstprivate variables.<br>
       CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),<br>
@@ -1351,11 +1334,11 @@ CodeGenFunction::EmitSections(const OMPE<br>
   bool HasFirstprivates;<br>
   // No need to generate reductions for sections with single section region, we<br>
   // can use original shared variables for all operations.<br>
-  bool HasReductions = !S.getClausesOfKind(OMPC_reduction).empty();<br>
+  bool HasReductions = S.hasClausesOfKind<OMPReductionClause>();<br>
   // No need to generate lastprivates for sections with single section region,<br>
   // we can use original shared variable for all calculations with barrier at<br>
   // the end of the sections.<br>
-  bool HasLastprivates = !S.getClausesOfKind(OMPC_lastprivate).empty();<br>
+  bool HasLastprivates = S.hasClausesOfKind<OMPLastprivateClause>();<br>
   auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) {<br>
     CodeGenFunction::OMPPrivateScope SingleScope(CGF);<br>
     HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);<br>
@@ -1371,7 +1354,7 @@ CodeGenFunction::EmitSections(const OMPE<br>
   // 'sections' directive has 'nowait' clause. Otherwise the barrier will be<br>
   // generated by the codegen for the directive.<br>
   if ((HasFirstprivates || HasLastprivates || HasReductions) &&<br>
-      S.getSingleClause(OMPC_nowait)) {<br>
+      S.getSingleClause<OMPNowaitClause>()) {<br>
     // Emit implicit barrier to synchronize threads and avoid data races on<br>
     // initialization of firstprivate variables.<br>
     CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown);<br>
@@ -1383,7 +1366,7 @@ void CodeGenFunction::EmitOMPSectionsDir<br>
   LexicalScope Scope(*this, S.getSourceRange());<br>
   OpenMPDirectiveKind EmittedAs = EmitSections(S);<br>
   // Emit an implicit barrier at the end.<br>
-  if (!S.getSingleClause(OMPC_nowait)) {<br>
+  if (!S.getSingleClause<OMPNowaitClause>()) {<br>
     CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);<br>
   }<br>
 }<br>
@@ -1407,8 +1390,7 @@ void CodeGenFunction::EmitOMPSingleDirec<br>
   // construct.<br>
   // Build a list of copyprivate variables along with helper expressions<br>
   // (<source>, <destination>, <destination>=<source> expressions)<br>
-  for (auto &&I = S.getClausesOfKind(OMPC_copyprivate); I; ++I) {<br>
-    auto *C = cast<OMPCopyprivateClause>(*I);<br>
+  for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {<br>
     CopyprivateVars.append(C->varlists().begin(), C->varlists().end());<br>
     DestExprs.append(C->destination_exprs().begin(),<br>
                      C->destination_exprs().end());<br>
@@ -1433,11 +1415,11 @@ void CodeGenFunction::EmitOMPSingleDirec<br>
                                           AssignmentOps);<br>
   // Emit an implicit barrier at the end (to avoid data race on firstprivate<br>
   // init or if no 'nowait' clause was specified and no 'copyprivate' clause).<br>
-  if ((!S.getSingleClause(OMPC_nowait) || HasFirstprivates) &&<br>
+  if ((!S.getSingleClause<OMPNowaitClause>() || HasFirstprivates) &&<br>
       CopyprivateVars.empty()) {<br>
     CGM.getOpenMPRuntime().emitBarrierCall(<br>
         *this, S.getLocStart(),<br>
-        S.getSingleClause(OMPC_nowait) ? OMPD_unknown : OMPD_single);<br>
+        S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);<br>
   }<br>
 }<br>
<br>
@@ -1521,8 +1503,7 @@ void CodeGenFunction::EmitOMPTaskDirecti<br>
   // Get list of private variables.<br>
   llvm::SmallVector<const Expr *, 8> PrivateVars;<br>
   llvm::SmallVector<const Expr *, 8> PrivateCopies;<br>
-  for (auto &&I = S.getClausesOfKind(OMPC_private); I; ++I) {<br>
-    auto *C = cast<OMPPrivateClause>(*I);<br>
+  for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {<br>
     auto IRef = C->varlist_begin();<br>
     for (auto *IInit : C->private_copies()) {<br>
       auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());<br>
@@ -1538,8 +1519,7 @@ void CodeGenFunction::EmitOMPTaskDirecti<br>
   llvm::SmallVector<const Expr *, 8> FirstprivateVars;<br>
   llvm::SmallVector<const Expr *, 8> FirstprivateCopies;<br>
   llvm::SmallVector<const Expr *, 8> FirstprivateInits;<br>
-  for (auto &&I = S.getClausesOfKind(OMPC_firstprivate); I; ++I) {<br>
-    auto *C = cast<OMPFirstprivateClause>(*I);<br>
+  for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {<br>
     auto IRef = C->varlist_begin();<br>
     auto IElemInitRef = C->inits().begin();<br>
     for (auto *IInit : C->private_copies()) {<br>
@@ -1555,8 +1535,7 @@ void CodeGenFunction::EmitOMPTaskDirecti<br>
   // Build list of dependences.<br>
   llvm::SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 8><br>
       Dependences;<br>
-  for (auto &&I = S.getClausesOfKind(OMPC_depend); I; ++I) {<br>
-    auto *C = cast<OMPDependClause>(*I);<br>
+  for (const auto *C : S.getClausesOfKind<OMPDependClause>()) {<br>
     for (auto *IRef : C->varlists()) {<br>
       Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef));<br>
     }<br>
@@ -1608,13 +1587,13 @@ void CodeGenFunction::EmitOMPTaskDirecti<br>
   auto OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(<br>
       S, *I, OMPD_task, CodeGen);<br>
   // Check if we should emit tied or untied task.<br>
-  bool Tied = !S.getSingleClause(OMPC_untied);<br>
+  bool Tied = !S.getSingleClause<OMPUntiedClause>();<br>
   // Check if the task is final<br>
   llvm::PointerIntPair<llvm::Value *, 1, bool> Final;<br>
-  if (auto *Clause = S.getSingleClause(OMPC_final)) {<br>
+  if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {<br>
     // If the condition constant folds and can be elided, try to avoid emitting<br>
     // the condition and the dead arm of the if/else.<br>
-    auto *Cond = cast<OMPFinalClause>(Clause)->getCondition();<br>
+    auto *Cond = Clause->getCondition();<br>
     bool CondConstant;<br>
     if (ConstantFoldsToSimpleInteger(Cond, CondConstant))<br>
       Final.setInt(CondConstant);<br>
@@ -1626,8 +1605,8 @@ void CodeGenFunction::EmitOMPTaskDirecti<br>
   }<br>
   auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());<br>
   const Expr *IfCond = nullptr;<br>
-  if (auto C = S.getSingleClause(OMPC_if)) {<br>
-    IfCond = cast<OMPIfClause>(C)->getCondition();<br>
+  if (const auto *C = S.getSingleClause<OMPIfClause>()) {<br>
+    IfCond = C->getCondition();<br>
   }<br>
   CGM.getOpenMPRuntime().emitTaskCall(<br>
       *this, S.getLocStart(), S, Tied, Final, OutlinedFn, SharedsTy,<br>
@@ -1660,8 +1639,7 @@ void CodeGenFunction::EmitOMPTaskgroupDi<br>
<br>
 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {<br>
   CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef<const Expr *> {<br>
-    if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) {<br>
-      auto FlushClause = cast<OMPFlushClause>(C);<br>
+    if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) {<br>
       return llvm::makeArrayRef(FlushClause->varlist_begin(),<br>
                                 FlushClause->varlist_end());<br>
     }<br>
@@ -2084,7 +2062,7 @@ static void EmitOMPAtomicExpr(CodeGenFun<br>
 }<br>
<br>
 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {<br>
-  bool IsSeqCst = S.getSingleClause(/*K=*/OMPC_seq_cst);<br>
+  bool IsSeqCst = S.getSingleClause<OMPSeqCstClause>();<br>
   OpenMPClauseKind Kind = OMPC_unknown;<br>
   for (auto *C : S.clauses()) {<br>
     // Find first clause (skip seq_cst clause, if it is first).<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=246384&r1=246383&r2=246384&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=246384&r1=246383&r2=246384&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Sun Aug 30 10:12:28 2015<br>
@@ -3514,24 +3514,18 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKin<br>
 }<br>
<br>
 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {<br>
-  auto &&CollapseFilter = [](const OMPClause *C) -> bool {<br>
-    return C->getClauseKind() == OMPC_collapse;<br>
-  };<br>
-  OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I(<br>
-      Clauses, std::move(CollapseFilter));<br>
-  if (I)<br>
-    return cast<OMPCollapseClause>(*I)->getNumForLoops();<br>
+  auto CollapseClauses =<br>
+      OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);<br>
+  if (CollapseClauses.begin() != CollapseClauses.end())<br>
+    return (*CollapseClauses.begin())->getNumForLoops();<br>
   return nullptr;<br>
 }<br>
<br>
 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {<br>
-  auto &&OrderedFilter = [](const OMPClause *C) -> bool {<br>
-    return C->getClauseKind() == OMPC_ordered;<br>
-  };<br>
-  OMPExecutableDirective::filtered_clause_iterator<decltype(OrderedFilter)> I(<br>
-      Clauses, std::move(OrderedFilter));<br>
-  if (I)<br>
-    return cast<OMPOrderedClause>(*I)->getNumForLoops();<br>
+  auto OrderedClauses =<br>
+      OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);<br>
+  if (OrderedClauses.begin() != OrderedClauses.end())<br>
+    return (*OrderedClauses.begin())->getNumForLoops();<br>
   return nullptr;<br>
 }<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>