<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Hi Samuel,<br>
      Thanks for the review.<br>
      <blockquote type="cite">
        <div>If I understand it correctly, the reason for having a
          Clause instance for the flush directive is to enable the use
          of the machinery that parses the clauses for this directive as
          well. I think that this deserves a more thorough comment here.
          I would prefer the term implicit clause instead of pseudo
          here. In SemaOpenMP.cpp, 'implicit' is currently used in the
          code related to the flush directive. </div>
      </blockquote>
      Ok, I'll do that.<br>
      <br>
      <blockquote type="cite"> OpenMPClauseKind
        clang::getOpenMPClauseKind(StringRef Str) {<br>
        +  if (Str == "flush")<br>
        +    return OMPC_unknown;<br>
        <div><br>
        </div>
        <div>I suggest adding a comment here on why the special case for
          flush and link it with the comment about pseudo/implicit
          clauses.</div>
      </blockquote>
      I'll add the comment.<br>
      <br>
      <blockquote type="cite">+#pragma omp flush // expected-error
        {{'#pragma omp flush' cannot be an immediate substatement}}<br>
        <div><br>
        </div>
        <div>I think "cannot have" seems more accurate than "cannot be"
          in the diagnostic message.</div>
      </blockquote>
      Samuel, I don't quite understand how to express the same idea with
      "cannot have". Could you provide an example of the error message
      you'd like to see?<br>
      <blockquote type="cite">+#pragma omp flush(argc) flush(argc) //
        expected-warning {{extra tokens at the end of '#pragma omp
        flush' are ignored}}<br>
        +#pragma omp parallel flush(argc) // expected-warning {{extra
        tokens at the end of '#pragma omp parallel' are ignored}}<br>
        <div><br>
        </div>
        <div>I would expect these two last warnings to be errors. That
          is my understanding of "standalone directive" in the OpenMP
          spec. Gcc currently emits an error for the same constructs,
          so, unless there is a strong reason to emit the warning, I
          think clang should also emit an error here.</div>
      </blockquote>
      I don't agree. 'flush' is a directive name and there are no
      clauses with the name 'flush'. So, if you specify 'flush' clause,
      it should not be recognized by the Parser. The Parser should
      return the same result as if there are some extra tokens at the
      end of the directive (for clang it is a warning).<br>
      <br>
      <pre class="moz-signature" cols="72">Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team</pre>
      25.07.2014 23:36, Samuel F Antao пишет:<br>
    </div>
    <blockquote
cite="mid:CAK4VZWAPzWaV6Wge7BYUbG1ZXbUTKGnAWZqCWRnvxt_rAmizug@mail.gmail.com"
      type="cite">
      <div dir="ltr">Hi Alexey,
        <div><br>
        </div>
        <div>Thanks for the commit. I took a close look into this commit
          and my comments are bellow.</div>
        <div><br>
        </div>
        <div>Regards,</div>
        <div>Samuel</div>
        <div class="gmail_extra"><br>
          <br>
          <div class="gmail_quote">2014-07-21 7:26 GMT-04:00 Alexey
            Bataev <span dir="ltr"><<a moz-do-not-send="true"
                href="mailto:a.bataev@hotmail.com" target="_blank">a.bataev@hotmail.com</a>></span>:<br>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              Author: abataev<br>
              Date: Mon Jul 21 06:26:11 2014<br>
              New Revision: 213512<br>
              <br>
              URL: <a moz-do-not-send="true"
                href="http://llvm.org/viewvc/llvm-project?rev=213512&view=rev"
                target="_blank">http://llvm.org/viewvc/llvm-project?rev=213512&view=rev</a><br>
              Log:<br>
              [OPENMP] Initial parsing and sema analysis for 'flush'
              directive.<br>
              <br>
              Added:<br>
                  cfe/trunk/test/OpenMP/flush_ast_print.cpp   (with
              props)<br>
                  cfe/trunk/test/OpenMP/flush_messages.cpp   (with
              props)<br>
              Modified:<br>
                  cfe/trunk/include/clang-c/Index.h<br>
                  cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
                  cfe/trunk/include/clang/AST/OpenMPClause.h<br>
                  cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
                  cfe/trunk/include/clang/AST/StmtOpenMP.h<br>
                  cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
                  cfe/trunk/include/clang/Basic/OpenMPKinds.def<br>
                  cfe/trunk/include/clang/Basic/StmtNodes.td<br>
                  cfe/trunk/include/clang/Sema/Sema.h<br>
                  cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
                  cfe/trunk/lib/AST/Stmt.cpp<br>
                  cfe/trunk/lib/AST/StmtPrinter.cpp<br>
                  cfe/trunk/lib/AST/StmtProfile.cpp<br>
                  cfe/trunk/lib/Basic/OpenMPKinds.cpp<br>
                  cfe/trunk/lib/CodeGen/CGStmt.cpp<br>
                  cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp<br>
                  cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
                  cfe/trunk/lib/Parse/ParseOpenMP.cpp<br>
                  cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
                  cfe/trunk/lib/Sema/TreeTransform.h<br>
                  cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
                  cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
                  cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp<br>
                  cfe/trunk/test/OpenMP/nesting_of_regions.cpp<br>
                  cfe/trunk/tools/libclang/CIndex.cpp<br>
                  cfe/trunk/tools/libclang/CXCursor.cpp<br>
              <br>
              Modified: cfe/trunk/include/clang-c/Index.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang-c/Index.h (original)<br>
              +++ cfe/trunk/include/clang-c/Index.h Mon Jul 21 06:26:11
              2014<br>
              @@ -2187,9 +2187,13 @@ enum CXCursorKind {<br>
                  */<br>
                 CXCursor_OMPTaskwaitDirective          = 245,<br>
              <br>
              +  /** \brief OpenMP flush directive.<br>
              +   */<br>
              +  CXCursor_OMPFlushDirective             = 246,<br>
              +<br>
                 /** \brief Windows Structured Exception Handling's
              leave statement.<br>
                  */<br>
              -  CXCursor_SEHLeaveStmt                  = 246,<br>
              +  CXCursor_SEHLeaveStmt                  = 247,<br>
              <br>
                 CXCursor_LastStmt                      =
              CXCursor_SEHLeaveStmt,<br>
              <br>
              <br>
              Modified:
              cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
              (original)<br>
              +++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
              Mon Jul 21 06:26:11 2014<br>
              @@ -2323,6 +2323,9 @@
              DEF_TRAVERSE_STMT(OMPBarrierDirective,<br>
               DEF_TRAVERSE_STMT(OMPTaskwaitDirective,<br>
                                 {
              TRY_TO(TraverseOMPExecutableDirective(S)); })<br>
              <br>
              +DEF_TRAVERSE_STMT(OMPFlushDirective,<br>
              +                  {
              TRY_TO(TraverseOMPExecutableDirective(S)); })<br>
              +<br>
               // OpenMP clauses.<br>
               template <typename Derived><br>
               bool
              RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause
              *C) {<br>
              @@ -2481,6 +2484,12 @@
              RecursiveASTVisitor<Derived>::VisitOMPRe<br>
                 TRY_TO(VisitOMPClauseList(C));<br>
                 return true;<br>
               }<br>
              +<br>
              +template <typename Derived><br>
              +bool
              RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause
              *C) {<br>
              +  TRY_TO(VisitOMPClauseList(C));<br>
              +  return true;<br>
              +}<br>
              <br>
               // FIXME: look at the following tricky-seeming exprs to
              see if we<br>
               // need to recurse on anything.  These are ones that have
              methods<br>
              <br>
              Modified: cfe/trunk/include/clang/AST/OpenMPClause.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/AST/OpenMPClause.h (original)<br>
              +++ cfe/trunk/include/clang/AST/OpenMPClause.h Mon Jul 21
              06:26:11 2014<br>
              @@ -1390,6 +1390,66 @@ public:<br>
                 }<br>
               };<br>
              <br>
            </blockquote>
            <div><br>
            </div>
            <div>If I understand it correctly, the reason for having a
              Clause instance for the flush directive is to enable the
              use of the machinery that parses the clauses for this
              directive as well. I think that this deserves a more
              thorough comment here. I would prefer the term implicit
              clause instead of pseudo here. In SemaOpenMP.cpp,
              'implicit' is currently used in the code related to the
              flush directive. </div>
            <div> </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              +/// \brief This represents pseudo clause 'flush' for the
              '#pragma omp flush'<br>
              +/// directive.<br>
              +///<br>
              +/// \code<br>
              +/// #pragma omp flush(a,b)<br>
              +/// \endcode<br>
              +/// In this example directive '#pragma omp flush' has
              pseudo clause 'flush'<br>
              +/// with the variables 'a' and 'b'.<br>
              +///<br>
              +class OMPFlushClause : public
              OMPVarListClause<OMPFlushClause> {<br>
              +  /// \brief Build clause with number of variables \a N.<br>
              +  ///<br>
              +  /// \param StartLoc Starting location of the clause.<br>
              +  /// \param LParenLoc Location of '('.<br>
              +  /// \param EndLoc Ending location of the clause.<br>
              +  /// \param N Number of the variables in the clause.<br>
              +  ///<br>
              +  OMPFlushClause(SourceLocation StartLoc, SourceLocation
              LParenLoc,<br>
              +                 SourceLocation EndLoc, unsigned N)<br>
              +      :
              OMPVarListClause<OMPFlushClause>(OMPC_flush,
              StartLoc, LParenLoc,<br>
              +                                         EndLoc, N) {}<br>
              +<br>
              +  /// \brief Build an empty clause.<br>
              +  ///<br>
              +  /// \param N Number of variables.<br>
              +  ///<br>
              +  explicit OMPFlushClause(unsigned N)<br>
              +      :
              OMPVarListClause<OMPFlushClause>(OMPC_flush,
              SourceLocation(),<br>
              +                                        
              SourceLocation(), SourceLocation(),<br>
              +                                         N) {}<br>
              +<br>
              +public:<br>
              +  /// \brief Creates clause with a list of variables \a
              VL.<br>
              +  ///<br>
              +  /// \param C AST context.<br>
              +  /// \param StartLoc Starting location of the clause.<br>
              +  /// \param LParenLoc Location of '('.<br>
              +  /// \param EndLoc Ending location of the clause.<br>
              +  /// \param VL List of references to the variables.<br>
              +  ///<br>
              +  static OMPFlushClause *Create(const ASTContext &C,
              SourceLocation StartLoc,<br>
              +                                SourceLocation LParenLoc,
              SourceLocation EndLoc,<br>
              +                                ArrayRef<Expr *>
              VL);<br>
              +  /// \brief Creates an empty clause with \a N variables.<br>
              +  ///<br>
              +  /// \param C AST context.<br>
              +  /// \param N The number of variables.<br>
              +  ///<br>
              +  static OMPFlushClause *CreateEmpty(const ASTContext
              &C, unsigned N);<br>
              +<br>
              +  StmtRange children() {<br>
              +    return StmtRange(reinterpret_cast<Stmt
              **>(varlist_begin()),<br>
              +                     reinterpret_cast<Stmt
              **>(varlist_end()));<br>
              +  }<br>
              +<br>
              +  static bool classof(const OMPClause *T) {<br>
              +    return T->getClauseKind() == OMPC_flush;<br>
              +  }<br>
              +};<br>
              +<br>
               } // end namespace clang<br>
              <br>
               #endif<br>
              <br>
              Modified:
              cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
              (original)<br>
              +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon
              Jul 21 06:26:11 2014<br>
              @@ -2345,6 +2345,9 @@
              DEF_TRAVERSE_STMT(OMPBarrierDirective,<br>
               DEF_TRAVERSE_STMT(OMPTaskwaitDirective,<br>
                                 {
              TRY_TO(TraverseOMPExecutableDirective(S)); })<br>
              <br>
              +DEF_TRAVERSE_STMT(OMPFlushDirective,<br>
              +                  {
              TRY_TO(TraverseOMPExecutableDirective(S)); })<br>
              +<br>
               // OpenMP clauses.<br>
               template <typename Derived><br>
               bool
              RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause
              *C) {<br>
              @@ -2503,6 +2506,12 @@
              RecursiveASTVisitor<Derived>::VisitOMPRe<br>
                 TRY_TO(VisitOMPClauseList(C));<br>
                 return true;<br>
               }<br>
              +<br>
              +template <typename Derived><br>
              +bool
              RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause
              *C) {<br>
              +  TRY_TO(VisitOMPClauseList(C));<br>
              +  return true;<br>
              +}<br>
              <br>
               // FIXME: look at the following tricky-seeming exprs to
              see if we<br>
               // need to recurse on anything.  These are ones that have
              methods<br>
              <br>
              Modified: cfe/trunk/include/clang/AST/StmtOpenMP.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/AST/StmtOpenMP.h (original)<br>
              +++ cfe/trunk/include/clang/AST/StmtOpenMP.h Mon Jul 21
              06:26:11 2014<br>
              @@ -969,6 +969,65 @@ public:<br>
                 }<br>
               };<br>
              <br>
              +/// \brief This represents '#pragma omp flush' directive.<br>
              +///<br>
              +/// \code<br>
              +/// #pragma omp flush(a,b)<br>
              +/// \endcode<br>
              +/// In this example directive '#pragma omp flush' has 2
              arguments- variables 'a'<br>
              +/// and 'b'.<br>
              +/// 'omp flush' directive does not have clauses but have
              an optional list of<br>
              +/// variables to flush. This list of variables is stored
              within some fake clause<br>
              +/// FlushClause.<br>
              +class OMPFlushDirective : public OMPExecutableDirective {<br>
              +  friend class ASTStmtReader;<br>
              +  /// \brief Build directive with the given start and end
              location.<br>
              +  ///<br>
              +  /// \param StartLoc Starting location of the directive
              kind.<br>
              +  /// \param EndLoc Ending location of the directive.<br>
              +  /// \param NumClauses Number of clauses.<br>
              +  ///<br>
              +  OMPFlushDirective(SourceLocation StartLoc,
              SourceLocation EndLoc,<br>
              +                    unsigned NumClauses)<br>
              +      : OMPExecutableDirective(this,
              OMPFlushDirectiveClass, OMPD_flush,<br>
              +                               StartLoc, EndLoc,
              NumClauses, 0) {}<br>
              +<br>
              +  /// \brief Build an empty directive.<br>
              +  ///<br>
              +  /// \param NumClauses Number of clauses.<br>
              +  ///<br>
              +  explicit OMPFlushDirective(unsigned NumClauses)<br>
              +      : OMPExecutableDirective(this,
              OMPFlushDirectiveClass, OMPD_flush,<br>
              +                               SourceLocation(),
              SourceLocation(), NumClauses,<br>
              +                               0) {}<br>
              +<br>
              +public:<br>
              +  /// \brief Creates directive with a list of \a Clauses.<br>
              +  ///<br>
              +  /// \param C AST context.<br>
              +  /// \param StartLoc Starting location of the directive
              kind.<br>
              +  /// \param EndLoc Ending Location of the directive.<br>
              +  /// \param Clauses List of clauses (only single
              OMPFlushClause clause is<br>
              +  /// allowed).<br>
              +  ///<br>
              +  static OMPFlushDirective *Create(const ASTContext
              &C, SourceLocation StartLoc,<br>
              +                                   SourceLocation EndLoc,<br>
              +                                   ArrayRef<OMPClause
              *> Clauses);<br>
              +<br>
              +  /// \brief Creates an empty directive with the place
              for \a NumClauses<br>
              +  /// clauses.<br>
              +  ///<br>
              +  /// \param C AST context.<br>
              +  /// \param NumClauses Number of clauses.<br>
              +  ///<br>
              +  static OMPFlushDirective *CreateEmpty(const ASTContext
              &C,<br>
              +                                        unsigned
              NumClauses, EmptyShell);<br>
              +<br>
              +  static bool classof(const Stmt *T) {<br>
              +    return T->getStmtClass() ==
              OMPFlushDirectiveClass;<br>
              +  }<br>
              +};<br>
              +<br>
               } // end namespace clang<br>
              <br>
               #endif<br>
              <br>
              Modified:
              cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
              (original)<br>
              +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
              Mon Jul 21 06:26:11 2014<br>
              @@ -903,7 +903,7 @@ def err_omp_unknown_directive :
              Error<<br>
               def err_omp_unexpected_directive : Error<<br>
                 "unexpected OpenMP directive '#pragma omp %0'">;<br>
               def err_omp_expected_punc : Error<<br>
              -  "expected ',' or ')' in '%0' clause">;<br>
              +  "expected ',' or ')' in '%0'
              %select{clause|directive}1">;<br>
               def err_omp_unexpected_clause : Error<<br>
                 "unexpected OpenMP clause '%0' in directive '#pragma
              omp %1'">;<br>
               def err_omp_more_one_clause : Error<<br>
              <br>
              Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/Basic/OpenMPKinds.def
              (original)<br>
              +++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Mon Jul
              21 06:26:11 2014<br>
              @@ -69,6 +69,7 @@ OPENMP_DIRECTIVE(critical)<br>
               OPENMP_DIRECTIVE(taskyield)<br>
               OPENMP_DIRECTIVE(barrier)<br>
               OPENMP_DIRECTIVE(taskwait)<br>
              +OPENMP_DIRECTIVE(flush)<br>
               OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")<br>
               OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel
              sections")<br>
              <br>
              @@ -94,6 +95,7 @@ OPENMP_CLAUSE(ordered, OMPOrderedClause)<br>
               OPENMP_CLAUSE(nowait, OMPNowaitClause)<br>
               OPENMP_CLAUSE(untied, OMPUntiedClause)<br>
               OPENMP_CLAUSE(mergeable, OMPMergeableClause)<br>
              +OPENMP_CLAUSE(flush, OMPFlushClause)<br>
              <br>
               // Clauses allowed for OpenMP directive 'parallel'.<br>
               OPENMP_PARALLEL_CLAUSE(if)<br>
              <br>
              Modified: cfe/trunk/include/clang/Basic/StmtNodes.td<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/Basic/StmtNodes.td (original)<br>
              +++ cfe/trunk/include/clang/Basic/StmtNodes.td Mon Jul 21
              06:26:11 2014<br>
              @@ -192,3 +192,4 @@ def OMPTaskDirective :
              DStmt<OMPExecutab<br>
               def OMPTaskyieldDirective :
              DStmt<OMPExecutableDirective>;<br>
               def OMPBarrierDirective :
              DStmt<OMPExecutableDirective>;<br>
               def OMPTaskwaitDirective :
              DStmt<OMPExecutableDirective>;<br>
              +def OMPFlushDirective :
              DStmt<OMPExecutableDirective>;<br>
              <br>
              Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
              +++ cfe/trunk/include/clang/Sema/Sema.h Mon Jul 21
              06:26:11 2014<br>
              @@ -7382,7 +7382,11 @@ public:<br>
                                                        SourceLocation
              EndLoc);<br>
                 /// \brief Called on well-formed '\#pragma omp
              taskwait'.<br>
                 StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation
              StartLoc,<br>
              -                                         SourceLocation
              EndLoc);<br>
              +                                          SourceLocation
              EndLoc);<br>
              +  /// \brief Called on well-formed '\#pragma omp flush'.<br>
              +  StmtResult
              ActOnOpenMPFlushDirective(ArrayRef<OMPClause *>
              Clauses,<br>
              +                                       SourceLocation
              StartLoc,<br>
              +                                       SourceLocation
              EndLoc);<br>
              <br>
                 OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind
              Kind,<br>
                                                        Expr *Expr,<br>
              @@ -7520,6 +7524,11 @@ public:<br>
                                                         SourceLocation
              StartLoc,<br>
                                                         SourceLocation
              LParenLoc,<br>
                                                         SourceLocation
              EndLoc);<br>
              +  /// \brief Called on well-formed 'flush' pseudo clause.<br>
              +  OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr
              *> VarList,<br>
              +                                    SourceLocation
              StartLoc,<br>
              +                                    SourceLocation
              LParenLoc,<br>
              +                                    SourceLocation
              EndLoc);<br>
              <br>
                 /// \brief The kind of conversion being performed.<br>
                 enum CheckedConversionKind {<br>
              <br>
              Modified:
              cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h
              (original)<br>
              +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h
              Mon Jul 21 06:26:11 2014<br>
              @@ -1354,6 +1354,7 @@ namespace clang {<br>
                     STMT_OMP_TASKYIELD_DIRECTIVE,<br>
                     STMT_OMP_BARRIER_DIRECTIVE,<br>
                     STMT_OMP_TASKWAIT_DIRECTIVE,<br>
              +      STMT_OMP_FLUSH_DIRECTIVE,<br>
              <br>
                     // ARC<br>
                     EXPR_OBJC_BRIDGED_CAST,     // ObjCBridgedCastExpr<br>
              <br>
              Modified: cfe/trunk/lib/AST/Stmt.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/AST/Stmt.cpp (original)<br>
              +++ cfe/trunk/lib/AST/Stmt.cpp Mon Jul 21 06:26:11 2014<br>
              @@ -1327,6 +1327,27 @@ OMPReductionClause
              *OMPReductionClause::<br>
                 return new (Mem) OMPReductionClause(N);<br>
               }<br>
              <br>
              +OMPFlushClause *OMPFlushClause::Create(const ASTContext
              &C,<br>
              +                                       SourceLocation
              StartLoc,<br>
              +                                       SourceLocation
              LParenLoc,<br>
              +                                       SourceLocation
              EndLoc,<br>
              +                                       ArrayRef<Expr
              *> VL) {<br>
              +  void *Mem =
              C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause),<br>
              +                                                
               llvm::alignOf<Expr *>()) +<br>
              +                         sizeof(Expr *) * VL.size());<br>
              +  OMPFlushClause *Clause =<br>
              +      new (Mem) OMPFlushClause(StartLoc, LParenLoc,
              EndLoc, VL.size());<br>
              +  Clause->setVarRefs(VL);<br>
              +  return Clause;<br>
              +}<br>
              +<br>
              +OMPFlushClause *OMPFlushClause::CreateEmpty(const
              ASTContext &C, unsigned N) {<br>
              +  void *Mem =
              C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause),<br>
              +                                                
               llvm::alignOf<Expr *>()) +<br>
              +                         sizeof(Expr *) * N);<br>
              +  return new (Mem) OMPFlushClause(N);<br>
              +}<br>
              +<br>
               OMPParallelDirective *OMPParallelDirective::Create(<br>
                                                             const
              ASTContext &C,<br>
                                                           
               SourceLocation StartLoc,<br>
              @@ -1635,3 +1656,25 @@ OMPTaskwaitDirective
              *OMPTaskwaitDirecti<br>
                 return new (Mem) OMPTaskwaitDirective();<br>
               }<br>
              <br>
              +OMPFlushDirective *OMPFlushDirective::Create(const
              ASTContext &C,<br>
              +                                            
              SourceLocation StartLoc,<br>
              +                                            
              SourceLocation EndLoc,<br>
              +                                            
              ArrayRef<OMPClause *> Clauses) {<br>
              +  unsigned Size =
              llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),<br>
              +                                          
              llvm::alignOf<OMPClause *>());<br>
              +  void *Mem = C.Allocate(Size + sizeof(OMPClause *) *
              Clauses.size());<br>
              +  OMPFlushDirective *Dir =<br>
              +      new (Mem) OMPFlushDirective(StartLoc, EndLoc,
              Clauses.size());<br>
              +  Dir->setClauses(Clauses);<br>
              +  return Dir;<br>
              +}<br>
              +<br>
              +OMPFlushDirective *OMPFlushDirective::CreateEmpty(const
              ASTContext &C,<br>
              +                                                
               unsigned NumClauses,<br>
              +                                                
               EmptyShell) {<br>
              +  unsigned Size =
              llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),<br>
              +                                          
              llvm::alignOf<OMPClause *>());<br>
              +  void *Mem = C.Allocate(Size + sizeof(OMPClause *) *
              NumClauses);<br>
              +  return new (Mem) OMPFlushDirective(NumClauses);<br>
              +}<br>
              +<br>
              <br>
              Modified: cfe/trunk/lib/AST/StmtPrinter.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)<br>
              +++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Jul 21 06:26:11
              2014<br>
              @@ -775,6 +775,12 @@ void
              OMPClausePrinter::VisitOMPCopypriva<br>
                 }<br>
               }<br>
              <br>
              +void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause
              *Node) {<br>
              +  if (!Node->varlist_empty()) {<br>
              +    VisitOMPClauseList(Node, '(');<br>
              +    OS << ")";<br>
              +  }<br>
              +}<br>
               }<br>
              <br>
 //===----------------------------------------------------------------------===//<br>
              @@ -875,6 +881,11 @@ void
              StmtPrinter::VisitOMPTaskwaitDirect<br>
                 PrintOMPExecutableDirective(Node);<br>
               }<br>
              <br>
              +void
              StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective
              *Node) {<br>
              +  Indent() << "#pragma omp flush ";<br>
              +  PrintOMPExecutableDirective(Node);<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               //  Expr printing methods.<br>
 //===----------------------------------------------------------------------===//<br>
              <br>
              Modified: cfe/trunk/lib/AST/StmtProfile.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/AST/StmtProfile.cpp (original)<br>
              +++ cfe/trunk/lib/AST/StmtProfile.cpp Mon Jul 21 06:26:11
              2014<br>
              @@ -352,6 +352,9 @@ void<br>
               OMPClauseProfiler::VisitOMPCopyprivateClause(const
              OMPCopyprivateClause *C) {<br>
                 VisitOMPClauseList(C);<br>
               }<br>
              +void OMPClauseProfiler::VisitOMPFlushClause(const
              OMPFlushClause *C) {<br>
              +  VisitOMPClauseList(C);<br>
              +}<br>
               }<br>
              <br>
               void<br>
              @@ -424,6 +427,10 @@ void
              StmtProfiler::VisitOMPTaskwaitDirec<br>
                 VisitOMPExecutableDirective(S);<br>
               }<br>
              <br>
              +void StmtProfiler::VisitOMPFlushDirective(const
              OMPFlushDirective *S) {<br>
              +  VisitOMPExecutableDirective(S);<br>
              +}<br>
              +<br>
               void StmtProfiler::VisitExpr(const Expr *S) {<br>
                 VisitStmt(S);<br>
               }<br>
              <br>
              Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)<br>
              +++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -46,6 +46,8 @@ const char *clang::getOpenMPDirectiveNam<br>
               }<br>
              <br>
               OpenMPClauseKind clang::getOpenMPClauseKind(StringRef
              Str) {<br>
              +  if (Str == "flush")<br>
              +    return OMPC_unknown;<br>
            </blockquote>
            <div><br>
            </div>
            <div>I suggest adding a comment here on why the special case
              for flush and link it with the comment about
              pseudo/implicit clauses.</div>
            <div> </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
                 return llvm::StringSwitch<OpenMPClauseKind>(Str)<br>
               #define OPENMP_CLAUSE(Name, Class) .Case(#Name,
              OMPC_##Name)<br>
               #include "clang/Basic/OpenMPKinds.def"<br>
              @@ -105,6 +107,7 @@ unsigned
              clang::getOpenMPSimpleClauseTyp<br>
                 case OMPC_nowait:<br>
                 case OMPC_untied:<br>
                 case OMPC_mergeable:<br>
              +  case OMPC_flush:<br>
                   break;<br>
                 }<br>
                 llvm_unreachable("Invalid OpenMP simple clause kind");<br>
              @@ -163,6 +166,7 @@ const char
              *clang::getOpenMPSimpleClause<br>
                 case OMPC_nowait:<br>
                 case OMPC_untied:<br>
                 case OMPC_mergeable:<br>
              +  case OMPC_flush:<br>
                   break;<br>
                 }<br>
                 llvm_unreachable("Invalid OpenMP simple clause kind");<br>
              @@ -253,6 +257,9 @@ bool
              clang::isAllowedClauseForDirective(<br>
                     break;<br>
                   }<br>
                   break;<br>
              +  case OMPD_flush:<br>
              +    return CKind == OMPC_flush;<br>
              +    break;<br>
                 case OMPD_unknown:<br>
                 case OMPD_threadprivate:<br>
                 case OMPD_section:<br>
              <br>
              Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)<br>
              +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Jul 21 06:26:11
              2014<br>
              @@ -218,6 +218,9 @@ void CodeGenFunction::EmitStmt(const
              Stm<br>
                 case Stmt::OMPTaskwaitDirectiveClass:<br>
                 
               EmitOMPTaskwaitDirective(cast<OMPTaskwaitDirective>(*S));<br>
                   break;<br>
              +  case Stmt::OMPFlushDirectiveClass:<br>
              +  
               EmitOMPFlushDirective(cast<OMPFlushDirective>(*S));<br>
              +    break;<br>
                 }<br>
               }<br>
              <br>
              <br>
              Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)<br>
              +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -124,3 +124,7 @@ void
              CodeGenFunction::EmitOMPTaskwaitDir<br>
                 llvm_unreachable("CodeGen for 'omp taskwait' is not
              supported yet.");<br>
               }<br>
              <br>
              +void CodeGenFunction::EmitOMPFlushDirective(const
              OMPFlushDirective &) {<br>
              +  llvm_unreachable("CodeGen for 'omp flush' is not
              supported yet.");<br>
              +}<br>
              +<br>
              <br>
              Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br>
              +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Jul 21
              06:26:11 2014<br>
              @@ -1935,6 +1935,7 @@ public:<br>
                 void EmitOMPTaskyieldDirective(const
              OMPTaskyieldDirective &S);<br>
                 void EmitOMPBarrierDirective(const OMPBarrierDirective
              &S);<br>
                 void EmitOMPTaskwaitDirective(const
              OMPTaskwaitDirective &S);<br>
              +  void EmitOMPFlushDirective(const OMPFlushDirective
              &S);<br>
              <br>
               
 //===--------------------------------------------------------------------===//<br>
                 //                         LValue Expression Emission<br>
              <br>
              Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)<br>
              +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -86,6 +86,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpen<br>
                 case OMPD_taskyield:<br>
                 case OMPD_barrier:<br>
                 case OMPD_taskwait:<br>
              +  case OMPD_flush:<br>
                 case OMPD_for:<br>
                 case OMPD_sections:<br>
                 case OMPD_section:<br>
              @@ -112,7 +113,7 @@ Parser::DeclGroupPtrTy
              Parser::ParseOpen<br>
               ///         annot_pragma_openmp 'parallel' | 'simd' |
              'for' | 'sections' |<br>
               ///         'section' | 'single' | 'master' | 'critical'
              [ '(' <name> ')' ] |<br>
               ///         'parallel for' | 'parallel sections' | 'task'
              | 'taskyield' |<br>
              -///         'barrier' | 'taskwait' {clause}
              annot_pragma_openmp_end<br>
              +///         'barrier' | 'taskwait' | 'flush' {clause}
              annot_pragma_openmp_end<br>
               ///<br>
               StmtResult<br>
               Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool
              StandAloneAllowed) {<br>
              @@ -130,6 +131,7 @@
              Parser::ParseOpenMPDeclarativeOrExecutab<br>
                 DeclarationNameInfo DirName;<br>
                 StmtResult Directive = StmtError();<br>
                 bool HasAssociatedStatement = true;<br>
              +  bool FlushHasClause = false;<br>
              <br>
                 switch (DKind) {<br>
                 case OMPD_threadprivate:<br>
              @@ -148,6 +150,13 @@
              Parser::ParseOpenMPDeclarativeOrExecutab<br>
                   }<br>
                   SkipUntil(tok::annot_pragma_openmp_end);<br>
                   break;<br>
              +  case OMPD_flush:<br>
              +    if (PP.LookAhead(0).is(tok::l_paren)) {<br>
              +      FlushHasClause = true;<br>
              +      // Push copy of the current token back to stream to
              properly parse<br>
              +      // pseudo-clause OMPFlushClause.<br>
              +      PP.EnterToken(Tok);<br>
              +    }<br>
                 case OMPD_taskyield:<br>
                 case OMPD_barrier:<br>
                 case OMPD_taskwait:<br>
              @@ -156,6 +165,7 @@
              Parser::ParseOpenMPDeclarativeOrExecutab<br>
                         << getOpenMPDirectiveName(DKind);<br>
                   }<br>
                   HasAssociatedStatement = false;<br>
              +    // Fall through for further analysis.<br>
                 case OMPD_parallel:<br>
                 case OMPD_simd:<br>
                 case OMPD_for:<br>
              @@ -192,9 +202,12 @@
              Parser::ParseOpenMPDeclarativeOrExecutab<br>
                   Actions.StartOpenMPDSABlock(DKind, DirName,
              Actions.getCurScope(), Loc);<br>
              <br>
                   while (Tok.isNot(tok::annot_pragma_openmp_end)) {<br>
              -      OpenMPClauseKind CKind = Tok.isAnnotation()<br>
              -                                   ? OMPC_unknown<br>
              -                                   :
              getOpenMPClauseKind(PP.getSpelling(Tok));<br>
              +      OpenMPClauseKind CKind =<br>
              +          Tok.isAnnotation()<br>
              +              ? OMPC_unknown<br>
              +              : FlushHasClause ? OMPC_flush<br>
              +                               :
              getOpenMPClauseKind(PP.getSpelling(Tok));<br>
              +      FlushHasClause = false;<br>
                     OMPClause *Clause =<br>
                         ParseOpenMPClause(DKind, CKind,
              !FirstClauses[CKind].getInt());<br>
                     FirstClauses[CKind].setInt(true);<br>
              @@ -324,7 +337,7 @@ bool
              Parser::ParseOpenMPSimpleVarList(Op<br>
               ///       | linear-clause | aligned-clause |
              collapse-clause |<br>
               ///       lastprivate-clause | reduction-clause |
              proc_bind-clause |<br>
               ///       schedule-clause | copyin-clause |
              copyprivate-clause | untied-clause |<br>
              -///       mergeable-clause<br>
              +///       mergeable-clause | flush-clause<br>
               ///<br>
               OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind
              DKind,<br>
                                                    OpenMPClauseKind
              CKind, bool FirstClause) {<br>
              @@ -407,6 +420,7 @@ OMPClause
              *Parser::ParseOpenMPClause(Ope<br>
                 case OMPC_aligned:<br>
                 case OMPC_copyin:<br>
                 case OMPC_copyprivate:<br>
              +  case OMPC_flush:<br>
                   Clause = ParseOpenMPVarListClause(CKind);<br>
                   break;<br>
                 case OMPC_unknown:<br>
              @@ -605,7 +619,7 @@ static bool ParseReductionId(Parser
              &P,<br>
               }<br>
              <br>
               /// \brief Parsing of OpenMP clause 'private',
              'firstprivate', 'lastprivate',<br>
              -/// 'shared', 'copyin', or 'reduction'.<br>
              +/// 'shared', 'copyin', 'copyprivate', 'flush' or
              'reduction'.<br>
               ///<br>
               ///    private-clause:<br>
               ///       'private' '(' list ')'<br>
              @@ -621,6 +635,10 @@ static bool ParseReductionId(Parser
              &P,<br>
               ///       'aligned' '(' list [ ':' alignment ] ')'<br>
               ///    reduction-clause:<br>
               ///       'reduction' '(' reduction-identifier ':' list
              ')'<br>
              +///    copyprivate-clause:<br>
              +///       'copyprivate' '(' list ')'<br>
              +///    flush-clause:<br>
              +///       'flush' '(' list ')'<br>
               ///<br>
               OMPClause
              *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {<br>
                 SourceLocation Loc = Tok.getLocation();<br>
              @@ -676,7 +694,10 @@ OMPClause
              *Parser::ParseOpenMPVarListCla<br>
                   else if (Tok.isNot(tok::r_paren) &&<br>
                            Tok.isNot(tok::annot_pragma_openmp_end)
              &&<br>
                            (!MayHaveTail || Tok.isNot(tok::colon)))<br>
              -      Diag(Tok, diag::err_omp_expected_punc) <<
              getOpenMPClauseName(Kind);<br>
              +      Diag(Tok, diag::err_omp_expected_punc)<br>
              +          << ((Kind == OMPC_flush) ?
              getOpenMPDirectiveName(OMPD_flush)<br>
              +                                   :
              getOpenMPClauseName(Kind))<br>
              +          << (Kind == OMPC_flush);<br>
                 }<br>
              <br>
                 // Parse ':' linear-step (or ':' alignment).<br>
              <br>
              Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)<br>
              +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Mon Jul 21 06:26:11
              2014<br>
              @@ -1085,6 +1085,14 @@ void
              Sema::ActOnOpenMPRegionStart(OpenMP<br>
                                            Params);<br>
                   break;<br>
                 }<br>
              +  case OMPD_flush: {<br>
              +    Sema::CapturedParamNameType Params[] = {<br>
              +        std::make_pair(StringRef(), QualType()) //
              __context with shared vars<br>
              +    };<br>
              +  
               ActOnCapturedRegionStart(DSAStack->getConstructLoc(),
              CurScope, CR_OpenMP,<br>
              +                             Params);<br>
              +    break;<br>
              +  }<br>
                 case OMPD_threadprivate:<br>
                   llvm_unreachable("OpenMP Directive is not allowed");<br>
                 case OMPD_unknown:<br>
              @@ -1114,6 +1122,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | parallel         | taskyield       | *            
                                   |<br>
                 // | parallel         | barrier         | *            
                                   |<br>
                 // | parallel         | taskwait        | *            
                                   |<br>
              +  // | parallel         | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | for              | parallel        | *            
                                   |<br>
                 // | for              | for             | +            
                                   |<br>
              @@ -1129,6 +1138,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | for              | taskyield       | *            
                                   |<br>
                 // | for              | barrier         | +            
                                   |<br>
                 // | for              | taskwait        | *            
                                   |<br>
              +  // | for              | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | master           | parallel        | *            
                                   |<br>
                 // | master           | for             | +            
                                   |<br>
              @@ -1144,6 +1154,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | master           | taskyield       | *            
                                   |<br>
                 // | master           | barrier         | +            
                                   |<br>
                 // | master           | taskwait        | *            
                                   |<br>
              +  // | master           | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | critical         | parallel        | *            
                                   |<br>
                 // | critical         | for             | +            
                                   |<br>
              @@ -1174,6 +1185,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | simd             | taskyield       |              
                                   |<br>
                 // | simd             | barrier         |              
                                   |<br>
                 // | simd             | taskwait        |              
                                   |<br>
              +  // | simd             | flush           |              
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | sections         | parallel        | *            
                                   |<br>
                 // | sections         | for             | +            
                                   |<br>
              @@ -1189,6 +1201,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | sections         | taskyield       | *            
                                   |<br>
                 // | sections         | barrier         | +            
                                   |<br>
                 // | sections         | taskwait        | *            
                                   |<br>
              +  // | sections         | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | section          | parallel        | *            
                                   |<br>
                 // | section          | for             | +            
                                   |<br>
              @@ -1204,6 +1217,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | section          | taskyield       | *            
                                   |<br>
                 // | section          | barrier         | +            
                                   |<br>
                 // | section          | taskwait        | *            
                                   |<br>
              +  // | section          | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | single           | parallel        | *            
                                   |<br>
                 // | single           | for             | +            
                                   |<br>
              @@ -1219,6 +1233,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | single           | taskyield       | *            
                                   |<br>
                 // | single           | barrier         | +            
                                   |<br>
                 // | single           | taskwait        | *            
                                   |<br>
              +  // | single           | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | parallel for     | parallel        | *            
                                   |<br>
                 // | parallel for     | for             | +            
                                   |<br>
              @@ -1234,6 +1249,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | parallel for     | taskyield       | *            
                                   |<br>
                 // | parallel for     | barrier         | +            
                                   |<br>
                 // | parallel for     | taskwait        | *            
                                   |<br>
              +  // | parallel for     | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | parallel sections| parallel        | *            
                                   |<br>
                 // | parallel sections| for             | +            
                                   |<br>
              @@ -1249,6 +1265,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | parallel sections| taskyield       | *            
                                   |<br>
                 // | parallel sections| barrier         | +            
                                   |<br>
                 // | parallel sections| taskwait        | *            
                                   |<br>
              +  // | parallel sections| flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 // | task             | parallel        | *            
                                   |<br>
                 // | task             | for             | +            
                                   |<br>
              @@ -1264,6 +1281,7 @@ static bool
              CheckNestingOfRegions(Sema &<br>
                 // | task             | taskyield       | *            
                                   |<br>
                 // | task             | barrier         | +            
                                   |<br>
                 // | task             | taskwait        | *            
                                   |<br>
              +  // | task             | flush           | *            
                                   |<br>
                 //
+------------------+-----------------+------------------------------------+<br>
                 if (Stack->getCurScope()) {<br>
                   auto ParentRegion = Stack->getParentDirective();<br>
              @@ -1371,6 +1389,7 @@ StmtResult
              Sema::ActOnOpenMPExecutableDi<br>
                 llvm::SmallVector<OMPClause *, 8>
              ClausesWithImplicit;<br>
                 llvm::DenseMap<VarDecl *, Expr *>
              VarsWithInheritedDSA;<br>
                 bool ErrorFound = false;<br>
              +  ClausesWithImplicit.append(Clauses.begin(),
              Clauses.end());<br>
                 if (AStmt) {<br>
                   assert(isa<CapturedStmt>(AStmt) &&
              "Captured statement expected");<br>
              <br>
              @@ -1381,7 +1400,6 @@ StmtResult
              Sema::ActOnOpenMPExecutableDi<br>
                     return StmtError();<br>
                   // Generate list of implicitly defined firstprivate
              variables.<br>
                   VarsWithInheritedDSA =
              DSAChecker.getVarsWithInheritedDSA();<br>
              -    ClausesWithImplicit.append(Clauses.begin(),
              Clauses.end());<br>
              <br>
                   if (!DSAChecker.getImplicitFirstprivate().empty()) {<br>
                     if (OMPClause *Implicit =
              ActOnOpenMPFirstprivateClause(<br>
              @@ -1464,6 +1482,11 @@ StmtResult
              Sema::ActOnOpenMPExecutableDi<br>
                          "No associated statement allowed for 'omp
              taskwait' directive");<br>
                   Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc);<br>
                   break;<br>
              +  case OMPD_flush:<br>
              +    assert(AStmt == nullptr &&<br>
              +           "No associated statement allowed for 'omp
              flush' directive");<br>
              +    Res = ActOnOpenMPFlushDirective(ClausesWithImplicit,
              StartLoc, EndLoc);<br>
              +    break;<br>
                 case OMPD_threadprivate:<br>
                   llvm_unreachable("OpenMP Directive is not allowed");<br>
                 case OMPD_unknown:<br>
              @@ -2234,6 +2257,13 @@ StmtResult
              Sema::ActOnOpenMPTaskwaitDire<br>
                 return OMPTaskwaitDirective::Create(Context, StartLoc,
              EndLoc);<br>
               }<br>
              <br>
              +StmtResult
              Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause
              *> Clauses,<br>
              +                                           SourceLocation
              StartLoc,<br>
              +                                           SourceLocation
              EndLoc) {<br>
              +  assert(Clauses.size() <= 1 && "Extra clauses
              in flush directive");<br>
              +  return OMPFlushDirective::Create(Context, StartLoc,
              EndLoc, Clauses);<br>
              +}<br>
              +<br>
               OMPClause
              *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
              Expr *Expr,<br>
                                                           
              SourceLocation StartLoc,<br>
                                                           
              SourceLocation LParenLoc,<br>
              @@ -2272,6 +2302,7 @@ OMPClause
              *Sema::ActOnOpenMPSingleExprCl<br>
                 case OMPC_untied:<br>
                 case OMPC_mergeable:<br>
                 case OMPC_threadprivate:<br>
              +  case OMPC_flush:<br>
                 case OMPC_unknown:<br>
                   llvm_unreachable("Clause is not allowed.");<br>
                 }<br>
              @@ -2474,6 +2505,7 @@ OMPClause
              *Sema::ActOnOpenMPSimpleClause<br>
                 case OMPC_untied:<br>
                 case OMPC_mergeable:<br>
                 case OMPC_threadprivate:<br>
              +  case OMPC_flush:<br>
                 case OMPC_unknown:<br>
                   llvm_unreachable("Clause is not allowed.");<br>
                 }<br>
              @@ -2588,6 +2620,7 @@ OMPClause
              *Sema::ActOnOpenMPSingleExprWi<br>
                 case OMPC_untied:<br>
                 case OMPC_mergeable:<br>
                 case OMPC_threadprivate:<br>
              +  case OMPC_flush:<br>
                 case OMPC_unknown:<br>
                   llvm_unreachable("Clause is not allowed.");<br>
                 }<br>
              @@ -2685,6 +2718,7 @@ OMPClause
              *Sema::ActOnOpenMPClause(OpenM<br>
                 case OMPC_default:<br>
                 case OMPC_proc_bind:<br>
                 case OMPC_threadprivate:<br>
              +  case OMPC_flush:<br>
                 case OMPC_unknown:<br>
                   llvm_unreachable("Clause is not allowed.");<br>
                 }<br>
              @@ -2748,6 +2782,9 @@ OMPClause
              *Sema::ActOnOpenMPVarListClaus<br>
                 case OMPC_copyprivate:<br>
                   Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc,
              LParenLoc, EndLoc);<br>
                   break;<br>
              +  case OMPC_flush:<br>
              +    Res = ActOnOpenMPFlushClause(VarList, StartLoc,
              LParenLoc, EndLoc);<br>
              +    break;<br>
                 case OMPC_if:<br>
                 case OMPC_final:<br>
                 case OMPC_num_threads:<br>
              @@ -4052,4 +4089,14 @@ OMPClause
              *Sema::ActOnOpenMPCopyprivateC<br>
                 return OMPCopyprivateClause::Create(Context, StartLoc,
              LParenLoc, EndLoc, Vars);<br>
               }<br>
              <br>
              +OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr
              *> VarList,<br>
              +                                        SourceLocation
              StartLoc,<br>
              +                                        SourceLocation
              LParenLoc,<br>
              +                                        SourceLocation
              EndLoc) {<br>
              +  if (VarList.empty())<br>
              +    return nullptr;<br>
              +<br>
              +  return OMPFlushClause::Create(Context, StartLoc,
              LParenLoc, EndLoc, VarList);<br>
              +}<br>
              +<br>
               #undef DSAStack<br>
              <br>
              Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
              +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Jul 21 06:26:11
              2014<br>
              @@ -1517,6 +1517,18 @@ public:<br>
                                                               
               EndLoc);<br>
                 }<br>
              <br>
              +  /// \brief Build a new OpenMP 'flush' pseudo clause.<br>
              +  ///<br>
              +  /// By default, performs semantic analysis to build the
              new OpenMP clause.<br>
              +  /// Subclasses may override this routine to provide
              different behavior.<br>
              +  OMPClause *RebuildOMPFlushClause(ArrayRef<Expr *>
              VarList,<br>
              +                                   SourceLocation
              StartLoc,<br>
              +                                   SourceLocation
              LParenLoc,<br>
              +                                   SourceLocation EndLoc)
              {<br>
              +    return getSema().ActOnOpenMPFlushClause(VarList,
              StartLoc, LParenLoc,<br>
              +                                            EndLoc);<br>
              +  }<br>
              +<br>
                 /// \brief Rebuild the operand to an Objective-C
              \@synchronized statement.<br>
                 ///<br>
                 /// By default, performs semantic analysis to build the
              new statement.<br>
              @@ -6610,6 +6622,17 @@
              TreeTransform<Derived>::TransformOMPTask<br>
                 return Res;<br>
               }<br>
              <br>
              +template <typename Derived><br>
              +StmtResult<br>
              +TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective
              *D) {<br>
              +  DeclarationNameInfo DirName;<br>
              +  getDerived().getSema().StartOpenMPDSABlock(OMPD_flush,
              DirName, nullptr,<br>
              +                                            
              D->getLocStart());<br>
              +  StmtResult Res =
              getDerived().TransformOMPExecutableDirective(D);<br>
              +  getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
              +  return Res;<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               // OpenMP clause transformation<br>
 //===----------------------------------------------------------------------===//<br>
              @@ -6869,6 +6892,20 @@
              TreeTransform<Derived>::TransformOMPCopy<br>
                     Vars, C->getLocStart(), C->getLParenLoc(),
              C->getLocEnd());<br>
               }<br>
              <br>
              +template <typename Derived><br>
              +OMPClause
              *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause
              *C) {<br>
              +  llvm::SmallVector<Expr *, 16> Vars;<br>
              +  Vars.reserve(C->varlist_size());<br>
              +  for (auto *VE : C->varlists()) {<br>
              +    ExprResult EVar =
              getDerived().TransformExpr(cast<Expr>(VE));<br>
              +    if (EVar.isInvalid())<br>
              +      return nullptr;<br>
              +    Vars.push_back(EVar.get());<br>
              +  }<br>
              +  return getDerived().RebuildOMPFlushClause(Vars,
              C->getLocStart(),<br>
              +                                          
               C->getLParenLoc(), C->getLocEnd());<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               // Expression transformation<br>
 //===----------------------------------------------------------------------===//<br>
              <br>
              Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
              (original)<br>
              +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Jul
              21 06:26:11 2014<br>
              @@ -1742,6 +1742,9 @@ OMPClause
              *OMPClauseReader::readClause()<br>
                 case OMPC_copyprivate:<br>
                   C = OMPCopyprivateClause::CreateEmpty(Context,
              Record[Idx++]);<br>
                   break;<br>
              +  case OMPC_flush:<br>
              +    C = OMPFlushClause::CreateEmpty(Context,
              Record[Idx++]);<br>
              +    break;<br>
                 }<br>
                 Visit(C);<br>
                 C->setLocStart(Reader->ReadSourceLocation(Record,
              Idx));<br>
              @@ -1908,6 +1911,16 @@ void
              OMPClauseReader::VisitOMPCopyprivat<br>
                 C->setVarRefs(Vars);<br>
               }<br>
              <br>
              +void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause
              *C) {<br>
              +
               C->setLParenLoc(Reader->ReadSourceLocation(Record,
              Idx));<br>
              +  unsigned NumVars = C->varlist_size();<br>
              +  SmallVector<Expr *, 16> Vars;<br>
              +  Vars.reserve(NumVars);<br>
              +  for (unsigned i = 0; i != NumVars; ++i)<br>
              +    Vars.push_back(Reader->Reader.ReadSubExpr());<br>
              +  C->setVarRefs(Vars);<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               // OpenMP Directives.<br>
 //===----------------------------------------------------------------------===//<br>
              @@ -2011,6 +2024,13 @@ void
              ASTStmtReader::VisitOMPTaskwaitDire<br>
                 VisitOMPExecutableDirective(D);<br>
               }<br>
              <br>
              +void
              ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective
              *D) {<br>
              +  VisitStmt(D);<br>
              +  // The NumClauses field was read in ReadStmtFromStream.<br>
              +  ++Idx;<br>
              +  VisitOMPExecutableDirective(D);<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               // ASTReader Implementation<br>
 //===----------------------------------------------------------------------===//<br>
              @@ -2561,6 +2581,11 @@ Stmt
              *ASTReader::ReadStmtFromStream(Modu<br>
                     S = OMPTaskwaitDirective::CreateEmpty(Context,
              Empty);<br>
                     break;<br>
              <br>
              +    case STMT_OMP_FLUSH_DIRECTIVE:<br>
              +      S = OMPFlushDirective::CreateEmpty(<br>
              +          Context, Record[ASTStmtReader::NumStmtFields],
              Empty);<br>
              +      break;<br>
              +<br>
                   case EXPR_CXX_OPERATOR_CALL:<br>
                     S = new (Context) CXXOperatorCallExpr(Context,
              Empty);<br>
                     break;<br>
              <br>
              Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
              (original)<br>
              +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Jul
              21 06:26:11 2014<br>
              @@ -1805,6 +1805,13 @@ void
              OMPClauseWriter::VisitOMPCopyprivat<br>
                   Writer->Writer.AddStmt(VE);<br>
               }<br>
              <br>
              +void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause
              *C) {<br>
              +  Record.push_back(C->varlist_size());<br>
              +
               Writer->Writer.AddSourceLocation(C->getLParenLoc(),
              Record);<br>
              +  for (auto *VE : C->varlists())<br>
              +    Writer->Writer.AddStmt(VE);<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               // OpenMP Directives.<br>
 //===----------------------------------------------------------------------===//<br>
              @@ -1916,6 +1923,13 @@ void
              ASTStmtWriter::VisitOMPTaskwaitDire<br>
                 Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;<br>
               }<br>
              <br>
              +void
              ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective
              *D) {<br>
              +  VisitStmt(D);<br>
              +  Record.push_back(D->getNumClauses());<br>
              +  VisitOMPExecutableDirective(D);<br>
              +  Code = serialization::STMT_OMP_FLUSH_DIRECTIVE;<br>
              +}<br>
              +<br>
 //===----------------------------------------------------------------------===//<br>
               // ASTWriter Implementation<br>
 //===----------------------------------------------------------------------===//<br>
              <br>
              Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
              (original)<br>
              +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon
              Jul 21 06:26:11 2014<br>
              @@ -745,6 +745,7 @@ void ExprEngine::Visit(const Stmt *S,
              Ex<br>
                   case Stmt::OMPTaskyieldDirectiveClass:<br>
                   case Stmt::OMPBarrierDirectiveClass:<br>
                   case Stmt::OMPTaskwaitDirectiveClass:<br>
              +    case Stmt::OMPFlushDirectiveClass:<br>
                     llvm_unreachable("Stmt should not be in analyzer
              evaluation loop");<br>
              <br>
                   case Stmt::ObjCSubscriptRefExprClass:<br>
              <br>
              Added: cfe/trunk/test/OpenMP/flush_ast_print.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/flush_ast_print.cpp?rev=213512&view=auto"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/flush_ast_print.cpp?rev=213512&view=auto</a><br>
==============================================================================<br>
              --- cfe/trunk/test/OpenMP/flush_ast_print.cpp (added)<br>
              +++ cfe/trunk/test/OpenMP/flush_ast_print.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -0,0 +1,38 @@<br>
              +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ast-print
              %s | FileCheck %s<br>
              +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11
              -emit-pch -o %t %s<br>
              +// RUN: %clang_cc1 -fopenmp=libiomp5 -std=c++11
              -include-pch %t -fsyntax-only -verify %s -ast-print |
              FileCheck %s<br>
              +// expected-no-diagnostics<br>
              +<br>
              +#ifndef HEADER<br>
              +#define HEADER<br>
              +<br>
              +void foo() {}<br>
              +<br>
              +template <class T><br>
              +T tmain(T argc) {<br>
              +  static T a;<br>
              +#pragma omp flush<br>
              +#pragma omp flush(a)<br>
              +  return a + argc;<br>
              +}<br>
              +// CHECK:      static int a;<br>
              +// CHECK-NEXT: #pragma omp flush<br>
              +// CHECK-NEXT: #pragma omp flush (a)<br>
              +// CHECK:      static char a;<br>
              +// CHECK-NEXT: #pragma omp flush<br>
              +// CHECK-NEXT: #pragma omp flush (a)<br>
              +// CHECK:      static T a;<br>
              +// CHECK-NEXT: #pragma omp flush<br>
              +// CHECK-NEXT: #pragma omp flush (a)<br>
              +<br>
              +int main(int argc, char **argv) {<br>
              +  static int a;<br>
              +// CHECK: static int a;<br>
              +#pragma omp flush<br>
              +#pragma omp flush(a)<br>
              +// CHECK-NEXT: #pragma omp flush<br>
              +// CHECK-NEXT: #pragma omp flush (a)<br>
              +  return tmain(argc) + tmain(argv[0][0]) + a;<br>
              +}<br>
              +<br>
              +#endif<br>
              <br>
              Propchange: cfe/trunk/test/OpenMP/flush_ast_print.cpp<br>
------------------------------------------------------------------------------<br>
                  <a class="moz-txt-link-freetext" href="svn:eol-style">svn:eol-style</a> = native<br>
              <br>
              Propchange: cfe/trunk/test/OpenMP/flush_ast_print.cpp<br>
------------------------------------------------------------------------------<br>
                  <a class="moz-txt-link-freetext" href="svn:keywords">svn:keywords</a> = Author Date Id Rev URL<br>
              <br>
              Propchange: cfe/trunk/test/OpenMP/flush_ast_print.cpp<br>
------------------------------------------------------------------------------<br>
                  <a class="moz-txt-link-freetext" href="svn:mime-type">svn:mime-type</a> = text/plain<br>
              <br>
              Added: cfe/trunk/test/OpenMP/flush_messages.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/flush_messages.cpp?rev=213512&view=auto"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/flush_messages.cpp?rev=213512&view=auto</a><br>
==============================================================================<br>
              --- cfe/trunk/test/OpenMP/flush_messages.cpp (added)<br>
              +++ cfe/trunk/test/OpenMP/flush_messages.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -0,0 +1,134 @@<br>
              +// RUN: %clang_cc1 -verify -fopenmp=libiomp5
              -ferror-limit 100 %s<br>
              +<br>
              +struct S1 { // expected-note 2 {{declared here}}<br>
              +  int a;<br>
              +};<br>
              +<br>
              +template <class T><br>
              +T tmain(T argc) {<br>
              +#pragma omp flush<br>
              +  ;<br>
              +#pragma omp flush untied  // expected-error {{unexpected
              OpenMP clause 'untied' in directive '#pragma omp flush'}}<br>
              +#pragma omp flush unknown // expected-warning {{extra
              tokens at the end of '#pragma omp flush' are ignored}}<br>
              +  if (argc)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
            </blockquote>
            <div><br>
            </div>
            <div>I think "cannot have" seems more accurate than "cannot
              be" in the diagnostic message.</div>
            <div><br>
            </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              +    if (argc) {<br>
              +#pragma omp flush<br>
              +    }<br>
              +  while (argc)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    while (argc) {<br>
              +#pragma omp flush<br>
              +    }<br>
              +  do<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    while (argc)<br>
              +      ;<br>
              +  do {<br>
              +#pragma omp flush<br>
              +  } while (argc);<br>
              +  switch (argc)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    switch (argc)<br>
              +    case 1:<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +  switch (argc)<br>
              +  case 1: {<br>
              +#pragma omp flush<br>
              +  }<br>
              +  switch (argc) {<br>
              +#pragma omp flush<br>
              +  case 1:<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    break;<br>
              +  default: {<br>
              +#pragma omp flush<br>
              +  } break;<br>
              +  }<br>
              +  for (;;)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    for (;;) {<br>
              +#pragma omp flush<br>
              +    }<br>
              +label:<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +label1 : {<br>
              +#pragma omp flush<br>
              +}<br>
              +<br>
              +#pragma omp flush<br>
              +#pragma omp flush(                              //
              expected-error {{expected expression}} expected-error
              {{expected ')'}} expected-note {{to match this '('}}<br>
              +#pragma omp flush()                             //
              expected-error {{expected expression}}<br>
              +#pragma omp flush(argc                          //
              expected-error {{expected ')'}} expected-note {{to match
              this '('}}<br>
              +#pragma omp flush(argc,                         //
              expected-error {{expected expression}} expected-error
              {{expected ')'}} expected-note {{to match this '('}}<br>
              +#pragma omp flush(argc)<br>
              +#pragma omp flush(S1) // expected-error {{'S1' does not
              refer to a value}}<br>
              +#pragma omp flush(argc) flush(argc) // expected-warning
              {{extra tokens at the end of '#pragma omp flush' are
              ignored}}<br>
              +#pragma omp parallel flush(argc) // expected-warning
              {{extra tokens at the end of '#pragma omp parallel' are
              ignored}}<br>
            </blockquote>
            <div><br>
            </div>
            <div>I would expect these two last warnings to be errors.
              That is my understanding of "standalone directive" in the
              OpenMP spec. Gcc currently emits an error for the same
              constructs, so, unless there is a strong reason to emit
              the warning, I think clang should also emit an error here.</div>
            <div> </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              +  ;<br>
              +  return T();<br>
              +}<br>
              +<br>
              +int main(int argc, char **argv) {<br>
              +#pragma omp flush<br>
              +  ;<br>
              +#pragma omp flush untied  // expected-error {{unexpected
              OpenMP clause 'untied' in directive '#pragma omp flush'}}<br>
              +#pragma omp flush unknown // expected-warning {{extra
              tokens at the end of '#pragma omp flush' are ignored}}<br>
              +  if (argc)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    if (argc) {<br>
              +#pragma omp flush<br>
              +    }<br>
              +  while (argc)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    while (argc) {<br>
              +#pragma omp flush<br>
              +    }<br>
              +  do<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    while (argc)<br>
              +      ;<br>
              +  do {<br>
              +#pragma omp flush<br>
              +  } while (argc);<br>
              +  switch (argc)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    switch (argc)<br>
              +    case 1:<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +  switch (argc)<br>
              +  case 1: {<br>
              +#pragma omp flush<br>
              +  }<br>
              +  switch (argc) {<br>
              +#pragma omp flush<br>
              +  case 1:<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    break;<br>
              +  default: {<br>
              +#pragma omp flush<br>
              +  } break;<br>
              +  }<br>
              +  for (;;)<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +    for (;;) {<br>
              +#pragma omp flush<br>
              +    }<br>
              +label:<br>
              +#pragma omp flush // expected-error {{'#pragma omp flush'
              cannot be an immediate substatement}}<br>
              +label1 : {<br>
              +#pragma omp flush<br>
              +}<br>
              +<br>
              +#pragma omp flush<br>
              +#pragma omp flush(                              //
              expected-error {{expected expression}} expected-error
              {{expected ')'}} expected-note {{to match this '('}}<br>
              +#pragma omp flush()                             //
              expected-error {{expected expression}}<br>
              +#pragma omp flush(argc                          //
              expected-error {{expected ')'}} expected-note {{to match
              this '('}}<br>
              +#pragma omp flush(argc,                         //
              expected-error {{expected expression}} expected-error
              {{expected ')'}} expected-note {{to match this '('}}<br>
              +#pragma omp flush(argc)<br>
              +#pragma omp flush(S1) // expected-error {{'S1' does not
              refer to a value}}<br>
              +#pragma omp flush(argc) flush(argc) // expected-warning
              {{extra tokens at the end of '#pragma omp flush' are
              ignored}}<br>
              +#pragma omp parallel flush(argc) // expected-warning
              {{extra tokens at the end of '#pragma omp parallel' are
              ignored}}<br>
              +  ;<br>
              +  return tmain(argc);<br>
              +}<br>
              <br>
              Propchange: cfe/trunk/test/OpenMP/flush_messages.cpp<br>
------------------------------------------------------------------------------<br>
                  <a class="moz-txt-link-freetext" href="svn:eol-style">svn:eol-style</a> = native<br>
              <br>
              Propchange: cfe/trunk/test/OpenMP/flush_messages.cpp<br>
------------------------------------------------------------------------------<br>
                  <a class="moz-txt-link-freetext" href="svn:keywords">svn:keywords</a> = Author Date Id Rev URL<br>
              <br>
              Propchange: cfe/trunk/test/OpenMP/flush_messages.cpp<br>
------------------------------------------------------------------------------<br>
                  <a class="moz-txt-link-freetext" href="svn:mime-type">svn:mime-type</a> = text/plain<br>
              <br>
              Modified: cfe/trunk/test/OpenMP/nesting_of_regions.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/nesting_of_regions.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/nesting_of_regions.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/test/OpenMP/nesting_of_regions.cpp
              (original)<br>
              +++ cfe/trunk/test/OpenMP/nesting_of_regions.cpp Mon Jul
              21 06:26:11 2014<br>
              @@ -66,6 +66,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp parallel<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // SIMD DIRECTIVE<br>
               #pragma omp simd<br>
              @@ -156,6 +161,11 @@ void foo() {<br>
               #pragma omp taskwait // expected-error {{OpenMP
              constructs may not be nested inside a simd region}}<br>
                   bar();<br>
                 }<br>
              +#pragma omp simd<br>
              +  for (int i = 0; i < 10; ++i) {<br>
              +#pragma omp flush // expected-error {{OpenMP constructs
              may not be nested inside a simd region}}<br>
              +    bar();<br>
              +  }<br>
              <br>
               // FOR DIRECTIVE<br>
               #pragma omp for<br>
              @@ -264,6 +274,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp for<br>
              +  for (int i = 0; i < 10; ++i) {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // SECTIONS DIRECTIVE<br>
               #pragma omp sections<br>
              @@ -385,6 +400,10 @@ void foo() {<br>
                 {<br>
               #pragma omp taskwait<br>
                 }<br>
              +#pragma omp sections<br>
              +  {<br>
              +#pragma omp flush<br>
              +  }<br>
              <br>
               // SECTION DIRECTIVE<br>
               #pragma omp section // expected-error {{orphaned 'omp
              section' directives are prohibited, it must be closely
              nested to a sections region}}<br>
              @@ -523,6 +542,14 @@ void foo() {<br>
                     bar();<br>
                   }<br>
                 }<br>
              +#pragma omp sections<br>
              +  {<br>
              +#pragma omp section<br>
              +    {<br>
              +#pragma omp flush<br>
              +      bar();<br>
              +    }<br>
              +  }<br>
              <br>
               // SINGLE DIRECTIVE<br>
               #pragma omp single<br>
              @@ -623,6 +650,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp single<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // MASTER DIRECTIVE<br>
               #pragma omp master<br>
              @@ -723,6 +755,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp master<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // CRITICAL DIRECTIVE<br>
               #pragma omp critical<br>
              @@ -952,6 +989,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp parallel for<br>
              +  for (int i = 0; i < 10; ++i) {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // PARALLEL SECTIONS DIRECTIVE<br>
               #pragma omp parallel sections<br>
              @@ -1059,6 +1101,10 @@ void foo() {<br>
                 {<br>
               #pragma omp taskwait<br>
                 }<br>
              +#pragma omp parallel sections<br>
              +  {<br>
              +#pragma omp flush<br>
              +  }<br>
              <br>
               // TASK DIRECTIVE<br>
               #pragma omp task<br>
              @@ -1118,6 +1164,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp task<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
               }<br>
              <br>
               void foo() {<br>
              @@ -1183,6 +1234,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp parallel<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // SIMD DIRECTIVE<br>
               #pragma omp simd<br>
              @@ -1266,6 +1322,11 @@ void foo() {<br>
               #pragma omp taskwait // expected-error {{OpenMP
              constructs may not be nested inside a simd region}}<br>
                   bar();<br>
                 }<br>
              +#pragma omp simd<br>
              +  for (int i = 0; i < 10; ++i) {<br>
              +#pragma omp flush // expected-error {{OpenMP constructs
              may not be nested inside a simd region}}<br>
              +    bar();<br>
              +  }<br>
              <br>
               // FOR DIRECTIVE<br>
               #pragma omp for<br>
              @@ -1361,6 +1422,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp for<br>
              +  for (int i = 0; i < 10; ++i) {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // SECTIONS DIRECTIVE<br>
               #pragma omp sections<br>
              @@ -1454,6 +1520,10 @@ void foo() {<br>
                 {<br>
               #pragma omp taskwait<br>
                 }<br>
              +#pragma omp sections<br>
              +  {<br>
              +#pragma omp flush<br>
              +  }<br>
              <br>
               // SECTION DIRECTIVE<br>
               #pragma omp section // expected-error {{orphaned 'omp
              section' directives are prohibited, it must be closely
              nested to a sections region}}<br>
              @@ -1592,6 +1662,14 @@ void foo() {<br>
                     bar();<br>
                   }<br>
                 }<br>
              +#pragma omp sections<br>
              +  {<br>
              +#pragma omp section<br>
              +    {<br>
              +#pragma omp flush<br>
              +      bar();<br>
              +    }<br>
              +  }<br>
              <br>
               // SINGLE DIRECTIVE<br>
               #pragma omp single<br>
              @@ -1682,6 +1760,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp single<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // MASTER DIRECTIVE<br>
               #pragma omp master<br>
              @@ -1782,6 +1865,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp master<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // CRITICAL DIRECTIVE<br>
               #pragma omp critical<br>
              @@ -2010,6 +2098,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp parallel for<br>
              +  for (int i = 0; i < 10; ++i) {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
              <br>
               // PARALLEL SECTIONS DIRECTIVE<br>
               #pragma omp parallel sections<br>
              @@ -2113,6 +2206,10 @@ void foo() {<br>
                 {<br>
               #pragma omp taskwait<br>
                 }<br>
              +#pragma omp parallel sections<br>
              +  {<br>
              +#pragma omp flush<br>
              +  }<br>
              <br>
               // TASK DIRECTIVE<br>
               #pragma omp task<br>
              @@ -2171,6 +2268,11 @@ void foo() {<br>
               #pragma omp taskwait<br>
                   bar();<br>
                 }<br>
              +#pragma omp task<br>
              +  {<br>
              +#pragma omp flush<br>
              +    bar();<br>
              +  }<br>
                 return foo<int>();<br>
               }<br>
              <br>
              <br>
              Modified: cfe/trunk/tools/libclang/CIndex.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/tools/libclang/CIndex.cpp (original)<br>
              +++ cfe/trunk/tools/libclang/CIndex.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -1870,6 +1870,7 @@ public:<br>
                 void VisitOMPTaskyieldDirective(const
              OMPTaskyieldDirective *D);<br>
                 void VisitOMPBarrierDirective(const OMPBarrierDirective
              *D);<br>
                 void VisitOMPTaskwaitDirective(const
              OMPTaskwaitDirective *D);<br>
              +  void VisitOMPFlushDirective(const OMPFlushDirective
              *D);<br>
              <br>
               private:<br>
                 void AddDeclarationNameInfo(const Stmt *S);<br>
              @@ -2016,6 +2017,9 @@ void<br>
               OMPClauseEnqueue::VisitOMPCopyprivateClause(const
              OMPCopyprivateClause *C) {<br>
                 VisitOMPClauseList(C);<br>
               }<br>
              +void OMPClauseEnqueue::VisitOMPFlushClause(const
              OMPFlushClause *C) {<br>
              +  VisitOMPClauseList(C);<br>
              +}<br>
               }<br>
              <br>
               void EnqueueVisitor::EnqueueChildren(const OMPClause *S)
              {<br>
              @@ -2365,6 +2369,10 @@ void
              EnqueueVisitor::VisitOMPTaskwaitDir<br>
                 VisitOMPExecutableDirective(D);<br>
               }<br>
              <br>
              +void EnqueueVisitor::VisitOMPFlushDirective(const
              OMPFlushDirective *D) {<br>
              +  VisitOMPExecutableDirective(D);<br>
              +}<br>
              +<br>
               void CursorVisitor::EnqueueWorkList(VisitorWorkList
              &WL, const Stmt *S) {<br>
                 EnqueueVisitor(WL, MakeCXCursor(S, StmtParent,
              TU,RegionOfInterest)).Visit(S);<br>
               }<br>
              @@ -4065,6 +4073,8 @@ CXString
              clang_getCursorKindSpelling(enu<br>
                   return cxstring::createRef("OMPBarrierDirective");<br>
                 case CXCursor_OMPTaskwaitDirective:<br>
                   return cxstring::createRef("OMPTaskwaitDirective");<br>
              +  case CXCursor_OMPFlushDirective:<br>
              +    return cxstring::createRef("OMPFlushDirective");<br>
                 }<br>
              <br>
                 llvm_unreachable("Unhandled CXCursorKind");<br>
              <br>
              Modified: cfe/trunk/tools/libclang/CXCursor.cpp<br>
              URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=213512&r1=213511&r2=213512&view=diff"
                target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=213512&r1=213511&r2=213512&view=diff</a><br>
==============================================================================<br>
              --- cfe/trunk/tools/libclang/CXCursor.cpp (original)<br>
              +++ cfe/trunk/tools/libclang/CXCursor.cpp Mon Jul 21
              06:26:11 2014<br>
              @@ -559,6 +559,9 @@ CXCursor cxcursor::MakeCXCursor(const
              St<br>
                 case Stmt::OMPTaskwaitDirectiveClass:<br>
                   K = CXCursor_OMPTaskwaitDirective;<br>
                   break;<br>
              +  case Stmt::OMPFlushDirectiveClass:<br>
              +    K = CXCursor_OMPFlushDirective;<br>
              +    break;<br>
                 }<br>
              <br>
                 CXCursor C = { K, 0, { Parent, S, TU } };<br>
              <br>
              <br>
              _______________________________________________<br>
              cfe-commits mailing list<br>
              <a moz-do-not-send="true"
                href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
              <a moz-do-not-send="true"
                href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits"
                target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
            </blockquote>
          </div>
          <br>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>