head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC5:1.1.1.14
	netbsd-11-0-RC4:1.1.1.14
	netbsd-11-0-RC3:1.1.1.14
	netbsd-11-0-RC2:1.1.1.14
	netbsd-11-0-RC1:1.1.1.14
	perseant-exfatfs-base-20250801:1.1.1.14
	netbsd-11:1.1.1.14.0.10
	netbsd-11-base:1.1.1.14
	netbsd-10-1-RELEASE:1.1.1.14
	perseant-exfatfs-base-20240630:1.1.1.14
	perseant-exfatfs:1.1.1.14.0.8
	perseant-exfatfs-base:1.1.1.14
	netbsd-8-3-RELEASE:1.1.1.11
	netbsd-9-4-RELEASE:1.1.1.13
	netbsd-10-0-RELEASE:1.1.1.14
	netbsd-10-0-RC6:1.1.1.14
	netbsd-10-0-RC5:1.1.1.14
	netbsd-10-0-RC4:1.1.1.14
	netbsd-10-0-RC3:1.1.1.14
	netbsd-10-0-RC2:1.1.1.14
	netbsd-10-0-RC1:1.1.1.14
	netbsd-10:1.1.1.14.0.6
	netbsd-10-base:1.1.1.14
	netbsd-9-3-RELEASE:1.1.1.13
	cjep_sun2x:1.1.1.14.0.4
	cjep_sun2x-base:1.1.1.14
	cjep_staticlib_x-base1:1.1.1.14
	netbsd-9-2-RELEASE:1.1.1.13
	cjep_staticlib_x:1.1.1.14.0.2
	cjep_staticlib_x-base:1.1.1.14
	netbsd-9-1-RELEASE:1.1.1.13
	phil-wifi-20200421:1.1.1.14
	phil-wifi-20200411:1.1.1.14
	phil-wifi-20200406:1.1.1.14
	netbsd-8-2-RELEASE:1.1.1.11
	netbsd-9-0-RELEASE:1.1.1.13
	netbsd-9-0-RC2:1.1.1.13
	netbsd-9-0-RC1:1.1.1.13
	netbsd-9:1.1.1.13.0.2
	netbsd-9-base:1.1.1.13
	phil-wifi-20190609:1.1.1.13
	netbsd-8-1-RELEASE:1.1.1.11
	netbsd-8-1-RC1:1.1.1.11
	pgoyette-compat-merge-20190127:1.1.1.12.2.1
	pgoyette-compat-20190127:1.1.1.13
	pgoyette-compat-20190118:1.1.1.13
	pgoyette-compat-1226:1.1.1.13
	pgoyette-compat-1126:1.1.1.13
	pgoyette-compat-1020:1.1.1.13
	pgoyette-compat-0930:1.1.1.13
	pgoyette-compat-0906:1.1.1.13
	netbsd-7-2-RELEASE:1.1.1.7.2.1
	pgoyette-compat-0728:1.1.1.13
	clang-337282:1.1.1.13
	netbsd-8-0-RELEASE:1.1.1.11
	phil-wifi:1.1.1.12.0.4
	phil-wifi-base:1.1.1.12
	pgoyette-compat-0625:1.1.1.12
	netbsd-8-0-RC2:1.1.1.11
	pgoyette-compat-0521:1.1.1.12
	pgoyette-compat-0502:1.1.1.12
	pgoyette-compat-0422:1.1.1.12
	netbsd-8-0-RC1:1.1.1.11
	pgoyette-compat-0415:1.1.1.12
	pgoyette-compat-0407:1.1.1.12
	pgoyette-compat-0330:1.1.1.12
	pgoyette-compat-0322:1.1.1.12
	pgoyette-compat-0315:1.1.1.12
	netbsd-7-1-2-RELEASE:1.1.1.7.2.1
	pgoyette-compat:1.1.1.12.0.2
	pgoyette-compat-base:1.1.1.12
	netbsd-7-1-1-RELEASE:1.1.1.7.2.1
	clang-319952:1.1.1.12
	matt-nb8-mediatek:1.1.1.11.0.8
	matt-nb8-mediatek-base:1.1.1.11
	clang-309604:1.1.1.12
	perseant-stdc-iso10646:1.1.1.11.0.6
	perseant-stdc-iso10646-base:1.1.1.11
	netbsd-8:1.1.1.11.0.4
	netbsd-8-base:1.1.1.11
	prg-localcount2-base3:1.1.1.11
	prg-localcount2-base2:1.1.1.11
	prg-localcount2-base1:1.1.1.11
	prg-localcount2:1.1.1.11.0.2
	prg-localcount2-base:1.1.1.11
	pgoyette-localcount-20170426:1.1.1.11
	bouyer-socketcan-base1:1.1.1.11
	pgoyette-localcount-20170320:1.1.1.11
	netbsd-7-1:1.1.1.7.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.7.2.1
	netbsd-7-1-RC2:1.1.1.7.2.1
	clang-294123:1.1.1.11
	netbsd-7-nhusb-base-20170116:1.1.1.7.2.1
	bouyer-socketcan:1.1.1.10.0.2
	bouyer-socketcan-base:1.1.1.10
	clang-291444:1.1.1.10
	pgoyette-localcount-20170107:1.1.1.9
	netbsd-7-1-RC1:1.1.1.7.2.1
	pgoyette-localcount-20161104:1.1.1.9
	netbsd-7-0-2-RELEASE:1.1.1.7.2.1
	localcount-20160914:1.1.1.9
	netbsd-7-nhusb:1.1.1.7.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.7.2.1
	clang-280599:1.1.1.9
	pgoyette-localcount-20160806:1.1.1.9
	pgoyette-localcount-20160726:1.1.1.9
	pgoyette-localcount:1.1.1.9.0.2
	pgoyette-localcount-base:1.1.1.9
	netbsd-7-0-1-RELEASE:1.1.1.7.2.1
	clang-261930:1.1.1.9
	netbsd-7-0:1.1.1.7.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.7.2.1
	netbsd-7-0-RC3:1.1.1.7.2.1
	netbsd-7-0-RC2:1.1.1.7.2.1
	netbsd-7-0-RC1:1.1.1.7.2.1
	clang-237755:1.1.1.8
	clang-232565:1.1.1.8
	clang-227398:1.1.1.8
	tls-maxphys-base:1.1.1.7
	tls-maxphys:1.1.1.7.0.4
	netbsd-7:1.1.1.7.0.2
	netbsd-7-base:1.1.1.7
	clang-215315:1.1.1.7
	clang-209886:1.1.1.6
	yamt-pagecache:1.1.1.5.0.4
	yamt-pagecache-base9:1.1.1.5
	tls-earlyentropy:1.1.1.5.0.2
	tls-earlyentropy-base:1.1.1.6
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.5
	riastradh-drm2-base3:1.1.1.5
	clang-202566:1.1.1.5
	clang-201163:1.1.1.4
	clang-199312:1.1.1.3
	clang-198450:1.1.1.2
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.54;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.54;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.05.15.38.21;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	wh3aCSIWykURqWjx;

1.1.1.3
date	2014.01.15.21.26.18;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	NQXlzzA0SPkc5glx;

1.1.1.4
date	2014.02.14.20.07.04;	author joerg;	state Exp;
branches;
next	1.1.1.5;
commitid	annVkZ1sc17rF6px;

1.1.1.5
date	2014.03.04.19.53.31;	author joerg;	state Exp;
branches
	1.1.1.5.2.1
	1.1.1.5.4.1;
next	1.1.1.6;
commitid	29z1hJonZISIXprx;

1.1.1.6
date	2014.05.30.18.14.42;	author joerg;	state Exp;
branches;
next	1.1.1.7;
commitid	8q0kdlBlCn09GACx;

1.1.1.7
date	2014.08.10.17.08.25;	author joerg;	state Exp;
branches
	1.1.1.7.2.1
	1.1.1.7.4.1;
next	1.1.1.8;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.8
date	2015.01.29.19.57.31;	author joerg;	state Exp;
branches;
next	1.1.1.9;
commitid	mlISSizlPKvepX7y;

1.1.1.9
date	2016.02.27.22.11.48;	author joerg;	state Exp;
branches
	1.1.1.9.2.1;
next	1.1.1.10;
commitid	tIimz3oDlh1NpBWy;

1.1.1.10
date	2017.01.11.10.33.45;	author joerg;	state Exp;
branches
	1.1.1.10.2.1;
next	1.1.1.11;
commitid	CNnUNfII1jgNmxBz;

1.1.1.11
date	2017.02.09.17.38.06;	author joerg;	state Exp;
branches;
next	1.1.1.12;
commitid	UxB8JMFWM7xyMiFz;

1.1.1.12
date	2017.08.01.19.34.58;	author joerg;	state Exp;
branches
	1.1.1.12.2.1
	1.1.1.12.4.1;
next	1.1.1.13;
commitid	pMuDy65V0VicSx1A;

1.1.1.13
date	2018.07.17.18.30.57;	author joerg;	state Exp;
branches;
next	1.1.1.14;
commitid	wDzL46ALjrCZgwKA;

1.1.1.14
date	2019.11.13.22.19.26;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.5.2.1
date	2014.08.10.07.08.08;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.5.4.1
date	2014.03.04.19.53.31;	author yamt;	state dead;
branches;
next	1.1.1.5.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.5.4.2
date	2014.05.22.16.18.29;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.7.2.1
date	2015.06.04.20.04.29;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.7.4.1
date	2014.08.10.17.08.25;	author tls;	state dead;
branches;
next	1.1.1.7.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.7.4.2
date	2014.08.19.23.47.29;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.9.2.1
date	2017.03.20.06.52.39;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.10.2.1
date	2017.04.21.16.51.39;	author bouyer;	state Exp;
branches;
next	;
commitid	dUG7nkTKALCadqOz;

1.1.1.12.2.1
date	2018.07.28.04.33.21;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.12.4.1
date	2019.06.10.21.45.26;	author christos;	state Exp;
branches;
next	1.1.1.12.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.12.4.2
date	2020.04.13.07.46.36;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// \brief This file implements parsing of all OpenMP directives and clauses.
///
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
#include "RAIIObjectsForParser.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//

/// \brief Parsing of declarative OpenMP directives.
///
///       threadprivate-directive:
///         annot_pragma_openmp 'threadprivate' simple-variable-list
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
  ParenBraceBracketBalancer BalancerRAIIObj(*this);

  SourceLocation Loc = ConsumeToken();
  SmallVector<Expr *, 5> Identifiers;
  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
                                  OMPD_unknown :
                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));

  switch (DKind) {
  case OMPD_threadprivate:
    ConsumeToken();
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
          << getOpenMPDirectiveName(OMPD_threadprivate);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeToken();
      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
                                                       Identifiers);
    }
    break;
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    break;
  case OMPD_parallel:
  case OMPD_task:
  case NUM_OPENMP_DIRECTIVES:
    Diag(Tok, diag::err_omp_unexpected_directive)
      << getOpenMPDirectiveName(DKind);
    break;
  }
  SkipUntil(tok::annot_pragma_openmp_end);
  return DeclGroupPtrTy();
}

/// \brief Parsing of declarative or executable OpenMP directives.
///
///       threadprivate-directive:
///         annot_pragma_openmp 'threadprivate' simple-variable-list
///         annot_pragma_openmp_end
///
///       parallel-directive:
///         annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
///
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
  SmallVector<Expr *, 5> Identifiers;
  SmallVector<OMPClause *, 5> Clauses;
  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
                                               FirstClauses(NUM_OPENMP_CLAUSES);
  const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                              Scope::OpenMPDirectiveScope;
  SourceLocation Loc = ConsumeToken(), EndLoc;
  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
                                  OMPD_unknown :
                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));
  // Name of critical directive.
  DeclarationNameInfo DirName;
  StmtResult Directive = StmtError();

  switch (DKind) {
  case OMPD_threadprivate:
    ConsumeToken();
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
          << getOpenMPDirectiveName(OMPD_threadprivate);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      DeclGroupPtrTy Res =
        Actions.ActOnOpenMPThreadprivateDirective(Loc,
                                                  Identifiers);
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    }
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  case OMPD_parallel: {
    ConsumeToken();

    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());

    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      OpenMPClauseKind CKind = Tok.isAnnotation() ?
                                  OMPC_unknown :
                                  getOpenMPClauseKind(PP.getSpelling(Tok));
      OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
                                            !FirstClauses[CKind].getInt());
      FirstClauses[CKind].setInt(true);
      if (Clause) {
        FirstClauses[CKind].setPointer(Clause);
        Clauses.push_back(Clause);
      }

      // Skip ',' if any.
      if (Tok.is(tok::comma))
        ConsumeToken();
    }
    // End location of the directive.
    EndLoc = Tok.getLocation();
    // Consume final annot_pragma_openmp_end.
    ConsumeToken();

    StmtResult AssociatedStmt;
    bool CreateDirective = true;
    ParseScope OMPDirectiveScope(this, ScopeFlags);
    {
      // The body is a block scope like in Lambdas and Blocks.
      Sema::CompoundScopeRAII CompoundScope(Actions);
      Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1);
      Actions.ActOnStartOfCompoundStmt();
      // Parse statement
      AssociatedStmt = ParseStatement();
      Actions.ActOnFinishOfCompoundStmt();
      if (!AssociatedStmt.isUsable()) {
        Actions.ActOnCapturedRegionError();
        CreateDirective = false;
      } else {
        AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
        CreateDirective = AssociatedStmt.isUsable();
      }
    }
    if (CreateDirective)
      Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
                                                         AssociatedStmt.take(),
                                                         Loc, EndLoc);

    // Exit scope.
    Actions.EndOpenMPDSABlock(Directive.get());
    OMPDirectiveScope.Exit();
    }
    break;
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  case OMPD_task:
  case NUM_OPENMP_DIRECTIVES:
    Diag(Tok, diag::err_omp_unexpected_directive)
      << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  }
  return Directive;
}

/// \brief Parses list of simple variables for '#pragma omp threadprivate'
/// directive.
///
///   simple-variable-list:
///         '(' id-expression {, id-expression} ')'
///
bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
                                      SmallVectorImpl<Expr *> &VarList,
                                      bool AllowScopeSpecifier) {
  VarList.clear();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPDirectiveName(Kind)))
    return true;
  bool IsCorrect = true;
  bool NoIdentIsFound = true;

  // Read tokens while ')' or annot_pragma_openmp_end is not found.
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    CXXScopeSpec SS;
    SourceLocation TemplateKWLoc;
    UnqualifiedId Name;
    // Read var name.
    Token PrevTok = Tok;
    NoIdentIsFound = false;

    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
                                  TemplateKWLoc, Name)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
               Tok.isNot(tok::annot_pragma_openmp_end)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
      Diag(PrevTok.getLocation(), diag::err_expected_ident)
        << SourceRange(PrevTok.getLocation(), PrevTokLocation);
    } else {
      DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
      ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
                                                       NameInfo);
      if (Res.isUsable())
        VarList.push_back(Res.take());
    }
    // Consume ','.
    if (Tok.is(tok::comma)) {
      ConsumeToken();
    }
  }

  if (NoIdentIsFound) {
    Diag(Tok, diag::err_expected_ident);
    IsCorrect = false;
  }

  // Parse ')'.
  IsCorrect = !T.consumeClose() && IsCorrect;

  return !IsCorrect && VarList.empty();
}

/// \brief Parsing of OpenMP clauses.
///
///    clause:
///       default-clause|private-clause|firstprivate-clause|shared-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                     OpenMPClauseKind CKind, bool FirstClause) {
  OMPClause *Clause = 0;
  bool ErrorFound = false;
  // Check if clause is allowed for the given directive.
  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
    Diag(Tok, diag::err_omp_unexpected_clause)
      << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
    ErrorFound = true;
  }

  switch (CKind) {
  case OMPC_default:
    // OpenMP [2.9.3.1, Restrictions]
    //  Only a single default clause may be specified on a parallel or task
    //  directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
    }

    Clause = ParseOpenMPSimpleClause(CKind);
    break;
  case OMPC_private:
  case OMPC_firstprivate:
  case OMPC_shared:
    Clause = ParseOpenMPVarListClause(CKind);
    break;
  case OMPC_unknown:
    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
      << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  case OMPC_threadprivate:
  case NUM_OPENMP_CLAUSES:
    Diag(Tok, diag::err_omp_unexpected_clause)
      << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  }
  return ErrorFound ? 0 : Clause;
}

/// \brief Parsing of simple OpenMP clauses like 'default'.
///
///    default-clause:
///         'default' '(' 'none' | 'shared' ')
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return 0;

  unsigned Type = Tok.isAnnotation() ?
                     unsigned(OMPC_DEFAULT_unknown) :
                     getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
  SourceLocation TypeLoc = Tok.getLocation();
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  // Parse ')'.
  T.consumeClose();

  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
                                         Tok.getLocation());
}

/// \brief Parsing of OpenMP clause 'private', 'firstprivate',
/// 'shared', 'copyin', or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return 0;

  SmallVector<Expr *, 5> Vars;
  bool IsComma = true;
  while (IsComma || (Tok.isNot(tok::r_paren) &&
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
    // Parse variable
    ExprResult VarExpr = ParseAssignmentExpression();
    if (VarExpr.isUsable()) {
      Vars.push_back(VarExpr.take());
    } else {
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    // Skip ',' if any
    IsComma = Tok.is(tok::comma);
    if (IsComma) {
      ConsumeToken();
    } else if (Tok.isNot(tok::r_paren) &&
               Tok.isNot(tok::annot_pragma_openmp_end)) {
      Diag(Tok, diag::err_omp_expected_punc)
        << 1 << getOpenMPClauseName(Kind);
    }
  }

  // Parse ')'.
  T.consumeClose();
  if (Vars.empty())
    return 0;

  return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
                                          Tok.getLocation());
}

@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import clang 3.5svn r198450.
@
text
@d228 2
a229 3
      Diag(PrevTok.getLocation(), diag::err_expected)
          << tok::identifier
          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
d244 1
a244 1
    Diag(Tok, diag::err_expected) << tok::identifier;
@


1.1.1.3
log
@Import Clang 3.5svn r199312
@
text
@a14 1
#include "RAIIObjectsForParser.h"
d20 1
@


1.1.1.4
log
@Import Clang 3.5svn r201163.
@
text
@d370 1
a370 1
        << getOpenMPClauseName(Kind);
@


1.1.1.5
log
@Import Clang 3.5svn r202566.
@
text
@a62 1
  case OMPD_simd:
d117 1
a117 2
  case OMPD_parallel:
  case OMPD_simd: {
a271 10
  case OMPC_if:
    // OpenMP [2.5, Restrictions]
    //  At most one if clause can appear on the directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
    }

    Clause = ParseOpenMPSingleExprClause(CKind);
    break;
d273 3
a275 3
    // OpenMP [2.14.3.1, Restrictions]
    //  Only a single default clause may be specified on a parallel, task or
    //  teams directive.
a302 33
/// \brief Parsing of OpenMP clauses with single expressions like 'if',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
/// 'thread_limit'.
///
///    if-clause:
///      'if' '(' expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = ConsumeToken();

  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return 0;

  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));

  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  // Parse ')'.
  T.consumeClose();

  if (Val.isInvalid())
    return 0;

  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.take(), Loc,
                                             T.getOpenLocation(),
                                             T.getCloseLocation());
}

@


1.1.1.5.2.1
log
@Rebase.
@
text
@d14 1
a15 2
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
d38 3
a40 3
  OpenMPDirectiveKind DKind = Tok.isAnnotation()
                                  ? OMPD_unknown
                                  : getOpenMPDirectiveKind(PP.getSpelling(Tok));
d50 1
a50 1
            << getOpenMPDirectiveName(OMPD_threadprivate);
d55 2
a56 1
      return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
d65 1
d67 1
a67 1
        << getOpenMPDirectiveName(DKind);
d88 4
a91 4
  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
  FirstClauses(OMPC_unknown + 1);
  const unsigned ScopeFlags =
      Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
d93 3
a95 3
  OpenMPDirectiveKind DKind = Tok.isAnnotation()
                                  ? OMPD_unknown
                                  : getOpenMPDirectiveKind(PP.getSpelling(Tok));
d108 1
a108 1
            << getOpenMPDirectiveName(OMPD_threadprivate);
d112 2
a113 1
          Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
d125 5
a129 5
      OpenMPClauseKind CKind = Tok.isAnnotation()
                                   ? OMPC_unknown
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
      OMPClause *Clause =
          ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
d151 1
a151 1
      Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());
d160 1
a160 1
        AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
d165 3
a167 2
      Directive = Actions.ActOnOpenMPExecutableDirective(
          DKind, Clauses, AssociatedStmt.get(), Loc, EndLoc);
d172 1
a173 1
  }
d179 1
d181 1
a181 1
        << getOpenMPDirectiveName(DKind);
d235 2
a236 2
      ExprResult Res =
          Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
d238 1
a238 1
        VarList.push_back(Res.get());
d260 1
a260 3
///       if-clause | num_threads-clause | safelen-clause | default-clause |
///       private-clause | firstprivate-clause | shared-clause | linear-clause |
///       aligned-clause | collapse-clause
d264 1
a264 1
  OMPClause *Clause = nullptr;
d268 2
a269 2
    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
                                               << getOpenMPDirectiveName(DKind);
a274 3
  case OMPC_num_threads:
  case OMPC_safelen:
  case OMPC_collapse:
a276 4
    //  At most one num_threads clause can appear on the directive.
    // OpenMP [2.8.1, simd construct, Restrictions]
    //  Only one safelen  clause can appear on a simd directive.
    //  Only one collapse clause can appear on a simd directive.
d278 2
a279 2
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
a284 1
  case OMPC_proc_bind:
a287 2
    // OpenMP [2.5, parallel Construct, Restrictions]
    //  At most one proc_bind clause can appear on the directive.
d289 2
a290 2
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
a297 3
  case OMPC_linear:
  case OMPC_aligned:
  case OMPC_copyin:
d302 1
a302 1
        << getOpenMPDirectiveName(DKind);
d306 3
a308 2
    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
                                               << getOpenMPDirectiveName(DKind);
d312 1
a312 1
  return ErrorFound ? nullptr : Clause;
a321 9
///    num_threads-clause:
///      'num_threads' '(' expression ')'
///
///    safelen-clause:
///      'safelen' '(' expression ')'
///
///    collapse-clause:
///      'collapse' '(' expression ')'
///
d328 1
a328 1
    return nullptr;
d333 4
d341 1
a341 1
    return nullptr;
d343 3
a345 2
  return Actions.ActOnOpenMPSingleExprClause(
      Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
d348 1
a348 1
/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
a352 3
///    proc_bind-clause:
///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
///
d360 1
a360 1
    return nullptr;
d362 3
a364 2
  unsigned Type = getOpenMPSimpleClauseType(
      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
a385 4
///    linear-clause:
///       'linear' '(' list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
a389 1
  SourceLocation ColonLoc = SourceLocation();
d394 1
a394 1
    return nullptr;
d398 1
a398 2
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
a399 1
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
d403 1
a403 1
      Vars.push_back(VarExpr.get());
d410 1
a410 1
    if (IsComma)
d412 5
a416 18
    else if (Tok.isNot(tok::r_paren) &&
             Tok.isNot(tok::annot_pragma_openmp_end) &&
             (!MayHaveTail || Tok.isNot(tok::colon)))
      Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
  }

  // Parse ':' linear-step (or ':' alignment).
  Expr *TailExpr = nullptr;
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
  if (MustHaveTail) {
    ColonLoc = Tok.getLocation();
    ConsumeToken();
    ExprResult Tail = ParseAssignmentExpression();
    if (Tail.isUsable())
      TailExpr = Tail.get();
    else
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
d421 2
a422 2
  if (Vars.empty() || (MustHaveTail && !TailExpr))
    return nullptr;
d424 2
a425 2
  return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen,
                                          ColonLoc, Tok.getLocation());
@


1.1.1.6
log
@Import Clang 3.5svn r209886.
@
text
@d14 1
a15 2
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
d38 3
a40 3
  OpenMPDirectiveKind DKind = Tok.isAnnotation()
                                  ? OMPD_unknown
                                  : getOpenMPDirectiveKind(PP.getSpelling(Tok));
d50 1
a50 1
            << getOpenMPDirectiveName(OMPD_threadprivate);
d55 2
a56 1
      return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
d65 1
d67 1
a67 1
        << getOpenMPDirectiveName(DKind);
d88 4
a91 4
  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
  FirstClauses(OMPC_unknown + 1);
  const unsigned ScopeFlags =
      Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
d93 3
a95 3
  OpenMPDirectiveKind DKind = Tok.isAnnotation()
                                  ? OMPD_unknown
                                  : getOpenMPDirectiveKind(PP.getSpelling(Tok));
d108 1
a108 1
            << getOpenMPDirectiveName(OMPD_threadprivate);
d112 2
a113 1
          Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
d125 5
a129 5
      OpenMPClauseKind CKind = Tok.isAnnotation()
                                   ? OMPC_unknown
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
      OMPClause *Clause =
          ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
d151 1
a151 1
      Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());
d160 1
a160 1
        AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
d165 3
a167 2
      Directive = Actions.ActOnOpenMPExecutableDirective(
          DKind, Clauses, AssociatedStmt.get(), Loc, EndLoc);
d172 1
a173 1
  }
d179 1
d181 1
a181 1
        << getOpenMPDirectiveName(DKind);
d235 2
a236 2
      ExprResult Res =
          Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
d238 1
a238 1
        VarList.push_back(Res.get());
d260 1
a260 3
///       if-clause | num_threads-clause | safelen-clause | default-clause |
///       private-clause | firstprivate-clause | shared-clause | linear-clause |
///       aligned-clause | collapse-clause
d264 1
a264 1
  OMPClause *Clause = nullptr;
d268 2
a269 2
    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
                                               << getOpenMPDirectiveName(DKind);
a274 3
  case OMPC_num_threads:
  case OMPC_safelen:
  case OMPC_collapse:
a276 4
    //  At most one num_threads clause can appear on the directive.
    // OpenMP [2.8.1, simd construct, Restrictions]
    //  Only one safelen  clause can appear on a simd directive.
    //  Only one collapse clause can appear on a simd directive.
d278 2
a279 2
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
a284 1
  case OMPC_proc_bind:
a287 2
    // OpenMP [2.5, parallel Construct, Restrictions]
    //  At most one proc_bind clause can appear on the directive.
d289 2
a290 2
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
a297 3
  case OMPC_linear:
  case OMPC_aligned:
  case OMPC_copyin:
d302 1
a302 1
        << getOpenMPDirectiveName(DKind);
d306 3
a308 2
    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
                                               << getOpenMPDirectiveName(DKind);
d312 1
a312 1
  return ErrorFound ? nullptr : Clause;
a321 9
///    num_threads-clause:
///      'num_threads' '(' expression ')'
///
///    safelen-clause:
///      'safelen' '(' expression ')'
///
///    collapse-clause:
///      'collapse' '(' expression ')'
///
d328 1
a328 1
    return nullptr;
d333 4
d341 1
a341 1
    return nullptr;
d343 3
a345 2
  return Actions.ActOnOpenMPSingleExprClause(
      Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
d348 1
a348 1
/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
a352 3
///    proc_bind-clause:
///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
///
d360 1
a360 1
    return nullptr;
d362 3
a364 2
  unsigned Type = getOpenMPSimpleClauseType(
      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
a385 4
///    linear-clause:
///       'linear' '(' list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
a389 1
  SourceLocation ColonLoc = SourceLocation();
d394 1
a394 1
    return nullptr;
d398 1
a398 2
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
a399 1
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
d403 1
a403 1
      Vars.push_back(VarExpr.get());
d410 1
a410 1
    if (IsComma)
d412 5
a416 18
    else if (Tok.isNot(tok::r_paren) &&
             Tok.isNot(tok::annot_pragma_openmp_end) &&
             (!MayHaveTail || Tok.isNot(tok::colon)))
      Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
  }

  // Parse ':' linear-step (or ':' alignment).
  Expr *TailExpr = nullptr;
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
  if (MustHaveTail) {
    ColonLoc = Tok.getLocation();
    ConsumeToken();
    ExprResult Tail = ParseAssignmentExpression();
    if (Tail.isUsable())
      TailExpr = Tail.get();
    else
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
d421 2
a422 2
  if (Vars.empty() || (MustHaveTail && !TailExpr))
    return nullptr;
d424 2
a425 2
  return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen,
                                          ColonLoc, Tok.getLocation());
@


1.1.1.7
log
@Import clang 3.6svn r215315.
@
text
@a27 23
static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
  auto Tok = P.getCurToken();
  auto DKind =
      Tok.isAnnotation()
          ? OMPD_unknown
          : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
  if (DKind == OMPD_parallel) {
    Tok = P.getPreprocessor().LookAhead(0);
    auto SDKind =
        Tok.isAnnotation()
            ? OMPD_unknown
            : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
    if (SDKind == OMPD_for) {
      P.ConsumeToken();
      DKind = OMPD_parallel_for;
    } else if (SDKind == OMPD_sections) {
      P.ConsumeToken();
      DKind = OMPD_parallel_sections;
    }
  }
  return DKind;
}

d39 3
a41 1
  auto DKind = ParseOpenMPDirectiveKind(*this);
a64 14
  case OMPD_taskyield:
  case OMPD_barrier:
  case OMPD_taskwait:
  case OMPD_flush:
  case OMPD_for:
  case OMPD_sections:
  case OMPD_section:
  case OMPD_single:
  case OMPD_master:
  case OMPD_ordered:
  case OMPD_critical:
  case OMPD_parallel_for:
  case OMPD_parallel_sections:
  case OMPD_atomic:
d79 2
a80 6
///       executable-directive:
///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' {clause}
///         annot_pragma_openmp_end
d82 1
a82 2
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
d89 1
a89 1
  unsigned ScopeFlags =
d92 3
a94 1
  auto DKind = ParseOpenMPDirectiveKind(*this);
a97 2
  bool HasAssociatedStatement = true;
  bool FlushHasClause = false;
a115 16
  case OMPD_flush:
    if (PP.LookAhead(0).is(tok::l_paren)) {
      FlushHasClause = true;
      // Push copy of the current token back to stream to properly parse
      // pseudo-clause OMPFlushClause.
      PP.EnterToken(Tok);
    }
  case OMPD_taskyield:
  case OMPD_barrier:
  case OMPD_taskwait:
    if (!StandAloneAllowed) {
      Diag(Tok, diag::err_omp_immediate_directive)
          << getOpenMPDirectiveName(DKind);
    }
    HasAssociatedStatement = false;
    // Fall through for further analysis.
d117 1
a117 12
  case OMPD_simd:
  case OMPD_for:
  case OMPD_sections:
  case OMPD_single:
  case OMPD_section:
  case OMPD_master:
  case OMPD_critical:
  case OMPD_parallel_for:
  case OMPD_parallel_sections:
  case OMPD_task:
  case OMPD_ordered:
  case OMPD_atomic: {
a118 15
    // Parse directive name of the 'critical' directive if any.
    if (DKind == OMPD_critical) {
      BalancedDelimiterTracker T(*this, tok::l_paren,
                                 tok::annot_pragma_openmp_end);
      if (!T.consumeOpen()) {
        if (Tok.isAnyIdentifier()) {
          DirName =
              DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
          ConsumeAnyToken();
        } else {
          Diag(Tok, diag::err_omp_expected_identifier_for_critical);
        }
        T.consumeClose();
      }
    }
d120 1
a120 6
    if (isOpenMPLoopDirective(DKind))
      ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
    if (isOpenMPSimdDirective(DKind))
      ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
    ParseScope OMPDirectiveScope(this, ScopeFlags);
    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
d123 3
a125 6
      OpenMPClauseKind CKind =
          Tok.isAnnotation()
              ? OMPC_unknown
              : FlushHasClause ? OMPC_flush
                               : getOpenMPClauseKind(PP.getSpelling(Tok));
      FlushHasClause = false;
d145 2
a146 1
    if (HasAssociatedStatement) {
d149 1
a149 1
      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
d164 1
a164 1
          DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
d175 5
d256 3
a258 7
///       if-clause | final-clause | num_threads-clause | safelen-clause |
///       default-clause | private-clause | firstprivate-clause | shared-clause
///       | linear-clause | aligned-clause | collapse-clause |
///       lastprivate-clause | reduction-clause | proc_bind-clause |
///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
///       mergeable-clause | flush-clause | read-clause | write-clause |
///       update-clause | capture-clause | seq_cst-clause
a272 1
  case OMPC_final:
a281 3
    // OpenMP [2.11.1, task Construct, Restrictions]
    //  At most one if clause can appear on the directive.
    //  At most one final clause can appear on the directive.
a284 1
      ErrorFound = true;
a298 1
      ErrorFound = true;
a302 32
  case OMPC_schedule:
    // OpenMP [2.7.1, Restrictions, p. 3]
    //  Only one schedule clause can appear on a loop directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
      ErrorFound = true;
    }

    Clause = ParseOpenMPSingleExprWithArgClause(CKind);
    break;
  case OMPC_ordered:
  case OMPC_nowait:
  case OMPC_untied:
  case OMPC_mergeable:
  case OMPC_read:
  case OMPC_write:
  case OMPC_update:
  case OMPC_capture:
  case OMPC_seq_cst:
    // OpenMP [2.7.1, Restrictions, p. 9]
    //  Only one ordered clause can appear on a loop directive.
    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
    //  Only one nowait clause can appear on a for directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
      ErrorFound = true;
    }

    Clause = ParseOpenMPClause(CKind);
    break;
a304 1
  case OMPC_lastprivate:
a305 1
  case OMPC_reduction:
a308 2
  case OMPC_copyprivate:
  case OMPC_flush:
d326 1
a326 1
/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
a331 3
///    final-clause:
///      'final' '(' expression ')'
///
d393 2
a394 115
/// \brief Parsing of OpenMP clauses like 'ordered'.
///
///    ordered-clause:
///         'ordered'
///
///    nowait-clause:
///         'nowait'
///
///    untied-clause:
///         'untied'
///
///    mergeable-clause:
///         'mergeable'
///
///    read-clause:
///         'read'
///
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  ConsumeAnyToken();

  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
}


/// \brief Parsing of OpenMP clauses with single expressions and some additional
/// argument like 'schedule' or 'dist_schedule'.
///
///    schedule-clause:
///      'schedule' '(' kind [',' expression ] ')'
///
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = ConsumeToken();
  SourceLocation CommaLoc;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  ExprResult Val;
  unsigned Type = getOpenMPSimpleClauseType(
      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
  SourceLocation KLoc = Tok.getLocation();
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  if (Kind == OMPC_schedule &&
      (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
       Type == OMPC_SCHEDULE_guided) &&
      Tok.is(tok::comma)) {
    CommaLoc = ConsumeAnyToken();
    ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
    if (Val.isInvalid())
      return nullptr;
  }

  // Parse ')'.
  T.consumeClose();

  return Actions.ActOnOpenMPSingleExprWithArgClause(
      Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
      T.getCloseLocation());
}

static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
                             UnqualifiedId &ReductionId) {
  SourceLocation TemplateKWLoc;
  if (ReductionIdScopeSpec.isEmpty()) {
    auto OOK = OO_None;
    switch (P.getCurToken().getKind()) {
    case tok::plus:
      OOK = OO_Plus;
      break;
    case tok::minus:
      OOK = OO_Minus;
      break;
    case tok::star:
      OOK = OO_Star;
      break;
    case tok::amp:
      OOK = OO_Amp;
      break;
    case tok::pipe:
      OOK = OO_Pipe;
      break;
    case tok::caret:
      OOK = OO_Caret;
      break;
    case tok::ampamp:
      OOK = OO_AmpAmp;
      break;
    case tok::pipepipe:
      OOK = OO_PipePipe;
      break;
    default:
      break;
    }
    if (OOK != OO_None) {
      SourceLocation OpLoc = P.ConsumeToken();
      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
      return false;
    }
  }
  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
                              /*AllowDestructorName*/ false,
                              /*AllowConstructorName*/ false, ParsedType(),
                              TemplateKWLoc, ReductionId);
}

/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
a399 2
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
a405 6
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
a410 4
  // Optional scope specifier and unqualified id for reduction identifier.
  CXXScopeSpec ReductionIdScopeSpec;
  UnqualifiedId ReductionId;
  bool InvalidReductionId = false;
a416 19
  // Handle reduction-identifier for reduction clause.
  if (Kind == OMPC_reduction) {
    ColonProtectionRAIIObject ColonRAII(*this);
    if (getLangOpts().CPlusPlus) {
      ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
    }
    InvalidReductionId =
        ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
    if (InvalidReductionId) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
    }
  }

d418 1
a418 1
  bool IsComma = !InvalidReductionId;
d438 1
a438 4
      Diag(Tok, diag::err_omp_expected_punc)
          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
                                   : getOpenMPClauseName(Kind))
          << (Kind == OMPC_flush);
d457 1
a457 1
  if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
d460 2
a461 5
  return Actions.ActOnOpenMPVarListClause(
      Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
      ReductionIdScopeSpec,
      ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
                            : DeclarationNameInfo());
@


1.1.1.7.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@a28 9
  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
  // TODO: add other combined directives in topological order.
  const OpenMPDirectiveKind F[][3] = {
    { OMPD_for, OMPD_simd, OMPD_for_simd },
    { OMPD_parallel, OMPD_for, OMPD_parallel_for },
    { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
    { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }
  };
d34 12
a45 11
  for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
    if (DKind == F[i][0]) {
      Tok = P.getPreprocessor().LookAhead(0);
      auto SDKind =
          Tok.isAnnotation()
              ? OMPD_unknown
              : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
      if (SDKind == F[i][1]) {
        P.ConsumeToken();
        DKind = F[i][2];
      }
a90 1
  case OMPD_for_simd:
a97 1
  case OMPD_parallel_for_simd:
a99 2
  case OMPD_target:
  case OMPD_teams:
d118 1
a118 2
///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
///         'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
a174 1
  case OMPD_for_simd:
a180 1
  case OMPD_parallel_for_simd:
d184 1
a184 3
  case OMPD_atomic:
  case OMPD_target:
  case OMPD_teams: {
d701 1
a701 2
    ExprResult VarExpr =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
d727 1
a727 2
    ExprResult Tail =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
@


1.1.1.8
log
@Import Clang 3.6RC1 r227398.
@
text
@a28 9
  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
  // TODO: add other combined directives in topological order.
  const OpenMPDirectiveKind F[][3] = {
    { OMPD_for, OMPD_simd, OMPD_for_simd },
    { OMPD_parallel, OMPD_for, OMPD_parallel_for },
    { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
    { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }
  };
d34 12
a45 11
  for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
    if (DKind == F[i][0]) {
      Tok = P.getPreprocessor().LookAhead(0);
      auto SDKind =
          Tok.isAnnotation()
              ? OMPD_unknown
              : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
      if (SDKind == F[i][1]) {
        P.ConsumeToken();
        DKind = F[i][2];
      }
a90 1
  case OMPD_for_simd:
a97 1
  case OMPD_parallel_for_simd:
a99 2
  case OMPD_target:
  case OMPD_teams:
d118 1
a118 2
///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
///         'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
a174 1
  case OMPD_for_simd:
a180 1
  case OMPD_parallel_for_simd:
d184 1
a184 3
  case OMPD_atomic:
  case OMPD_target:
  case OMPD_teams: {
d701 1
a701 2
    ExprResult VarExpr =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
d727 1
a727 2
    ExprResult Tail =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
@


1.1.1.9
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a21 1

d33 5
a37 8
      {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/,
       OMPD_cancellation_point},
      {OMPD_target, OMPD_unknown /*data*/, OMPD_target_data},
      {OMPD_for, OMPD_simd, OMPD_for_simd},
      {OMPD_parallel, OMPD_for, OMPD_parallel_for},
      {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
      {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
      {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}};
a42 2

  bool TokenMatched = false;
d44 1
a44 9
    if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
      TokenMatched =
          (i == 0) &&
          !P.getPreprocessor().getSpelling(Tok).compare("cancellation");
    } else {
      TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
    }

    if (TokenMatched) {
a45 1
      auto TokenIsAnnotation = Tok.isAnnotation();
d47 1
a47 1
          TokenIsAnnotation
d50 1
a50 11

      if (!TokenIsAnnotation && SDKind == OMPD_unknown) {
        TokenMatched =
            ((i == 0) &&
             !P.getPreprocessor().getSpelling(Tok).compare("point")) ||
            ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data"));
      } else {
        TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
      }

      if (TokenMatched) {
a96 1
  case OMPD_taskgroup:
a111 6
  case OMPD_cancellation_point:
  case OMPD_cancel:
  case OMPD_target_data:
  case OMPD_taskloop:
  case OMPD_taskloop_simd:
  case OMPD_distribute:
d131 1
a131 3
///         'for simd' | 'parallel for simd' | 'target' | 'target data' |
///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} |
///         'distribute'
d134 2
a135 2
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
    AllowedContsructsKind Allowed) {
a145 1
  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
a153 4
    if (Allowed != ACK_Any) {
      Diag(Tok, diag::err_omp_immediate_directive)
          << getOpenMPDirectiveName(DKind) << 0;
    }
d179 1
a179 3
  case OMPD_cancellation_point:
  case OMPD_cancel:
    if (Allowed == ACK_StatementsOpenMPNonStandalone) {
d181 1
a181 1
          << getOpenMPDirectiveName(DKind) << 0;
d201 1
a201 6
  case OMPD_teams:
  case OMPD_taskgroup:
  case OMPD_target_data:
  case OMPD_taskloop:
  case OMPD_taskloop_simd:
  case OMPD_distribute: {
a216 4
    } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
      CancelRegion = ParseOpenMPDirectiveKind(*this);
      if (Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeToken();
a231 1
      Actions.StartOpenMPClause(CKind);
a243 1
      Actions.EndOpenMPClause();
a249 12
    // OpenMP [2.13.8, ordered Construct, Syntax]
    // If the depend clause is specified, the ordered construct is a stand-alone
    // directive.
    if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
      if (Allowed == ACK_StatementsOpenMPNonStandalone) {
        Diag(Loc, diag::err_omp_immediate_directive)
            << getOpenMPDirectiveName(DKind) << 1
            << getOpenMPClauseName(OMPC_depend);
      }
      HasAssociatedStatement = false;
    }

d251 1
d260 7
a266 1
      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
d268 3
a270 3
    Directive = Actions.ActOnOpenMPExecutableDirective(
        DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
        EndLoc);
d363 1
a363 4
///       update-clause | capture-clause | seq_cst-clause | device-clause |
///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
///       thread_limit-clause | priority-clause | grainsize-clause |
///       nogroup-clause | num_tasks-clause | hint-clause
d377 1
a380 1
  case OMPC_simdlen:
a381 8
  case OMPC_ordered:
  case OMPC_device:
  case OMPC_num_teams:
  case OMPC_thread_limit:
  case OMPC_priority:
  case OMPC_grainsize:
  case OMPC_num_tasks:
  case OMPC_hint:
d383 1
a386 1
    //  Only one simdlen  clause can appear on a simd directive.
a387 2
    // OpenMP [2.9.1, target data construct, Restrictions]
    //  At most one device clause can appear on the directive.
a390 9
    // OpenMP [teams Construct, Restrictions]
    //  At most one num_teams clause can appear on the directive.
    //  At most one thread_limit clause can appear on the directive.
    // OpenMP [2.9.1, task Construct, Restrictions]
    // At most one priority clause can appear on the directive.
    // OpenMP [2.9.2, taskloop Construct, Restrictions]
    // At most one grainsize clause can appear on the directive.
    // OpenMP [2.9.2, taskloop Construct, Restrictions]
    // At most one num_tasks clause can appear on the directive.
d392 2
a393 2
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
d397 1
a397 4
    if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
      Clause = ParseOpenMPClause(CKind);
    else
      Clause = ParseOpenMPSingleExprClause(CKind);
d407 2
a408 2
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
d418 2
a419 2
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
a422 1
  case OMPC_if:
d425 1
a433 3
  case OMPC_threads:
  case OMPC_simd:
  case OMPC_nogroup:
d439 2
a440 2
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
d456 1
a456 3
  case OMPC_depend:
  case OMPC_map:
    Clause = ParseOpenMPVarListClause(DKind, CKind);
d472 6
a477 3
/// \brief Parsing of OpenMP clauses with single expressions like 'final',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
a487 3
///    simdlen-clause:
///      'simdlen' '(' expression ')'
///
a490 12
///    priority-clause:
///      'priority' '(' expression ')'
///
///    grainsize-clause:
///      'grainsize' '(' expression ')'
///
///    num_tasks-clause:
///      'num_tasks' '(' expression ')'
///
///    hint-clause:
///      'hint' '(' expression ')'
///
a498 1
  SourceLocation ELoc = Tok.getLocation();
a500 1
  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
a559 9
///    threads-clause:
///         'threads'
///
///    simd-clause:
///         'simd'
///
///    nogroup-clause:
///         'nogroup'
///
d572 1
a572 5
///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
///      ')'
///
///    if-clause:
///      'if' '(' [ directive-name-modifier ':' ] expression ')'
d576 1
a576 1
  SourceLocation DelimLoc;
d584 6
a589 62
  SmallVector<unsigned, 4> Arg;
  SmallVector<SourceLocation, 4> KLoc;
  if (Kind == OMPC_schedule) {
    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
    Arg.resize(NumberOfElements);
    KLoc.resize(NumberOfElements);
    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
    auto KindModifier = getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
    if (KindModifier > OMPC_SCHEDULE_unknown) {
      // Parse 'modifier'
      Arg[Modifier1] = KindModifier;
      KLoc[Modifier1] = Tok.getLocation();
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
          Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
      if (Tok.is(tok::comma)) {
        // Parse ',' 'modifier'
        ConsumeAnyToken();
        KindModifier = getOpenMPSimpleClauseType(
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
                             ? KindModifier
                             : (unsigned)OMPC_SCHEDULE_unknown;
        KLoc[Modifier2] = Tok.getLocation();
        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
            Tok.isNot(tok::annot_pragma_openmp_end))
          ConsumeAnyToken();
      }
      // Parse ':'
      if (Tok.is(tok::colon))
        ConsumeAnyToken();
      else
        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
      KindModifier = getOpenMPSimpleClauseType(
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
    }
    Arg[ScheduleKind] = KindModifier;
    KLoc[ScheduleKind] = Tok.getLocation();
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
        Tok.is(tok::comma))
      DelimLoc = ConsumeAnyToken();
  } else {
    assert(Kind == OMPC_if);
    KLoc.push_back(Tok.getLocation());
    Arg.push_back(ParseOpenMPDirectiveKind(*this));
    if (Arg.back() != OMPD_unknown) {
      ConsumeToken();
      if (Tok.is(tok::colon))
        DelimLoc = ConsumeToken();
      else
        Diag(Tok, diag::warn_pragma_expected_colon)
            << "directive name modifier";
    }
  }
d591 5
a595 4
  bool NeedAnExpression =
      (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if;
  if (NeedAnExpression) {
    SourceLocation ELoc = Tok.getLocation();
d598 2
a599 1
    Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
a604 3
  if (NeedAnExpression && Val.isInvalid())
    return nullptr;

d606 1
a606 1
      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
d668 1
a668 1
///       'linear' '(' linear-list [ ':' linear-step ] ')'
d677 2
a678 12
///    depend-clause:
///       'depend' '(' in | out | inout : list | source ')'
///    map-clause:
///       'map' '(' [ [ always , ]
///          to | from | tofrom | alloc | release | delete ':' ] list ')';
///
/// For 'linear' clause linear-list may have the following forms:
///  list
///  modifier(list)
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
                                            OpenMPClauseKind Kind) {
a685 10
  OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
  // OpenMP 4.1 [2.15.3.7, linear Clause]
  //  If no modifier is specified it is assumed to be val.
  OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
  OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
  OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
  bool MapTypeModifierSpecified = false;
  bool UnexpectedId = false;
  SourceLocation DepLinMapLoc;

a691 3
  bool NeedRParenForLinear = false;
  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
                                  tok::annot_pragma_openmp_end);
a708 97
  } else if (Kind == OMPC_depend) {
  // Handle dependency type for depend clause.
    ColonProtectionRAIIObject ColonRAII(*this);
    DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
    DepLinMapLoc = Tok.getLocation();

    if (DepKind == OMPC_DEPEND_unknown) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else {
      ConsumeToken();
      // Special processing for depend(source) clause.
      if (DKind == OMPD_ordered && DepKind == OMPC_DEPEND_source) {
        // Parse ')'.
        T.consumeClose();
        return Actions.ActOnOpenMPVarListClause(
            Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen,
            /*ColonLoc=*/SourceLocation(), Tok.getLocation(),
            ReductionIdScopeSpec, DeclarationNameInfo(), DepKind,
            LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
      }
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
                                      : diag::warn_pragma_expected_colon)
          << "dependency type";
    }
  } else if (Kind == OMPC_linear) {
    // Try to parse modifier if any.
    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
      LinearModifier = static_cast<OpenMPLinearClauseKind>(
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
      DepLinMapLoc = ConsumeToken();
      LinearT.consumeOpen();
      NeedRParenForLinear = true;
    }
  } else if (Kind == OMPC_map) {
    // Handle map type for map clause.
    ColonProtectionRAIIObject ColonRAII(*this);

    // the first identifier may be a list item, a map-type or
    //   a map-type-modifier
    MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
    DepLinMapLoc = Tok.getLocation();
    bool ColonExpected = false;

    if (Tok.is(tok::identifier)) {
      if (PP.LookAhead(0).is(tok::colon)) {
        MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
            Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
        if (MapType == OMPC_MAP_unknown) {
          Diag(Tok, diag::err_omp_unknown_map_type);
        } else if (MapType == OMPC_MAP_always) {
          Diag(Tok, diag::err_omp_map_type_missing);
        }
        ConsumeToken();
      } else if (PP.LookAhead(0).is(tok::comma)) {
        if (PP.LookAhead(1).is(tok::identifier) &&
            PP.LookAhead(2).is(tok::colon)) {
          MapTypeModifier =
              static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
                   Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
          if (MapTypeModifier != OMPC_MAP_always) {
            Diag(Tok, diag::err_omp_unknown_map_type_modifier);
            MapTypeModifier = OMPC_MAP_unknown;
          } else {
            MapTypeModifierSpecified = true;
          }

          ConsumeToken();
          ConsumeToken();

          MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
              Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
          if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) {
            Diag(Tok, diag::err_omp_unknown_map_type);
          }
          ConsumeToken();
        } else {
          MapType = OMPC_MAP_tofrom;
        }
      } else {
        MapType = OMPC_MAP_tofrom;
      }
    } else {
      UnexpectedId = true;
    }

    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else if (ColonExpected) {
      Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
    }
d712 1
a712 8
  bool IsComma =
      ((Kind != OMPC_reduction) && (Kind != OMPC_depend) &&
       (Kind != OMPC_map)) ||
      ((Kind == OMPC_reduction) && !InvalidReductionId) ||
      ((Kind == OMPC_map) && (UnexpectedId || MapType != OMPC_MAP_unknown) &&
       (!MapTypeModifierSpecified ||
        (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) ||
      ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
a738 4
  // Parse ')' for linear clause with modifier.
  if (NeedRParenForLinear)
    LinearT.consumeClose();

d744 3
a746 3
    SourceLocation ELoc = ConsumeToken();
    ExprResult Tail = ParseAssignmentExpression();
    Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
d756 1
a756 4
  if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
      (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
      (Kind == OMPC_map && MapType == OMPC_MAP_unknown) ||
      InvalidReductionId) {
a757 1
  }
d763 1
a763 2
                            : DeclarationNameInfo(),
      DepKind, LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
@


1.1.1.9.2.1
log
@Sync with HEAD
@
text
@d15 1
a28 55
namespace {
enum OpenMPDirectiveKindEx {
  OMPD_cancellation = OMPD_unknown + 1,
  OMPD_data,
  OMPD_declare,
  OMPD_end,
  OMPD_end_declare,
  OMPD_enter,
  OMPD_exit,
  OMPD_point,
  OMPD_reduction,
  OMPD_target_enter,
  OMPD_target_exit,
  OMPD_update,
  OMPD_distribute_parallel,
  OMPD_teams_distribute_parallel,
  OMPD_target_teams_distribute_parallel
};

class ThreadprivateListParserHelper final {
  SmallVector<Expr *, 4> Identifiers;
  Parser *P;

public:
  ThreadprivateListParserHelper(Parser *P) : P(P) {}
  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
    ExprResult Res =
        P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
    if (Res.isUsable())
      Identifiers.push_back(Res.get());
  }
  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
};
} // namespace

// Map token string to extended OMP token kind that are
// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
static unsigned getOpenMPDirectiveKindEx(StringRef S) {
  auto DKind = getOpenMPDirectiveKind(S);
  if (DKind != OMPD_unknown)
    return DKind;

  return llvm::StringSwitch<unsigned>(S)
      .Case("cancellation", OMPD_cancellation)
      .Case("data", OMPD_data)
      .Case("declare", OMPD_declare)
      .Case("end", OMPD_end)
      .Case("enter", OMPD_enter)
      .Case("exit", OMPD_exit)
      .Case("point", OMPD_point)
      .Case("reduction", OMPD_reduction)
      .Case("update", OMPD_update)
      .Default(OMPD_unknown);
}

d33 9
a41 40
  static const unsigned F[][3] = {
    { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
    { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
    { OMPD_declare, OMPD_simd, OMPD_declare_simd },
    { OMPD_declare, OMPD_target, OMPD_declare_target },
    { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
    { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
    { OMPD_distribute_parallel_for, OMPD_simd, 
      OMPD_distribute_parallel_for_simd },
    { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
    { OMPD_end, OMPD_declare, OMPD_end_declare },
    { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
    { OMPD_target, OMPD_data, OMPD_target_data },
    { OMPD_target, OMPD_enter, OMPD_target_enter },
    { OMPD_target, OMPD_exit, OMPD_target_exit },
    { OMPD_target, OMPD_update, OMPD_target_update },
    { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
    { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
    { OMPD_for, OMPD_simd, OMPD_for_simd },
    { OMPD_parallel, OMPD_for, OMPD_parallel_for },
    { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
    { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
    { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
    { OMPD_target, OMPD_parallel, OMPD_target_parallel },
    { OMPD_target, OMPD_simd, OMPD_target_simd },
    { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
    { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
    { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
    { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
    { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
    { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
    { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
    { OMPD_target, OMPD_teams, OMPD_target_teams },
    { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
    { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
    { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
    { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
    { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
  };
  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
d43 1
a43 1
  unsigned DKind =
d45 2
a46 4
          ? static_cast<unsigned>(OMPD_unknown)
          : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
  if (DKind == OMPD_unknown)
    return OMPD_unknown;
d48 1
d50 4
a53 124
    if (DKind != F[i][0])
      continue;

    Tok = P.getPreprocessor().LookAhead(0);
    unsigned SDKind =
        Tok.isAnnotation()
            ? static_cast<unsigned>(OMPD_unknown)
            : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
    if (SDKind == OMPD_unknown)
      continue;

    if (SDKind == F[i][1]) {
      P.ConsumeToken();
      DKind = F[i][2];
    }
  }
  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
                              : OMPD_unknown;
}

static DeclarationName parseOpenMPReductionId(Parser &P) {
  Token Tok = P.getCurToken();
  Sema &Actions = P.getActions();
  OverloadedOperatorKind OOK = OO_None;
  // Allow to use 'operator' keyword for C++ operators
  bool WithOperator = false;
  if (Tok.is(tok::kw_operator)) {
    P.ConsumeToken();
    Tok = P.getCurToken();
    WithOperator = true;
  }
  switch (Tok.getKind()) {
  case tok::plus: // '+'
    OOK = OO_Plus;
    break;
  case tok::minus: // '-'
    OOK = OO_Minus;
    break;
  case tok::star: // '*'
    OOK = OO_Star;
    break;
  case tok::amp: // '&'
    OOK = OO_Amp;
    break;
  case tok::pipe: // '|'
    OOK = OO_Pipe;
    break;
  case tok::caret: // '^'
    OOK = OO_Caret;
    break;
  case tok::ampamp: // '&&'
    OOK = OO_AmpAmp;
    break;
  case tok::pipepipe: // '||'
    OOK = OO_PipePipe;
    break;
  case tok::identifier: // identifier
    if (!WithOperator)
      break;
  default:
    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                Parser::StopBeforeMatch);
    return DeclarationName();
  }
  P.ConsumeToken();
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
                        : DeclNames.getCXXOperatorName(OOK);
}

/// \brief Parse 'omp declare reduction' construct.
///
///       declare-reduction-directive:
///        annot_pragma_openmp 'declare' 'reduction'
///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
///        annot_pragma_openmp_end
/// <reduction_id> is either a base language identifier or one of the following
/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
///
Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPDirectiveName(OMPD_declare_reduction))) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  DeclarationName Name = parseOpenMPReductionId(*this);
  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Consume ':'.
  bool IsCorrect = !ExpectAndConsume(tok::colon);

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  IsCorrect = IsCorrect && !Name.isEmpty();

  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_expected_type);
    IsCorrect = false;
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
  // Parse list of types until ':' token.
  do {
    ColonProtectionRAIIObject ColonRAII(*this);
    SourceRange Range;
    TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
    if (TR.isUsable()) {
      auto ReductionType =
          Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
      if (!ReductionType.isNull()) {
        ReductionTypes.push_back(
            std::make_pair(ReductionType, Range.getBegin()));
      }
d55 1
a55 2
      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
d58 15
a72 9
    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
      break;

    // Consume ','.
    if (ExpectAndConsume(tok::comma)) {
      IsCorrect = false;
      if (Tok.is(tok::annot_pragma_openmp_end)) {
        Diag(Tok.getLocation(), diag::err_expected_type);
        return DeclGroupPtrTy();
a73 2
    }
  } while (Tok.isNot(tok::annot_pragma_openmp_end));
d75 3
a77 77
  if (ReductionTypes.empty()) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Consume ':'.
  if (ExpectAndConsume(tok::colon))
    IsCorrect = false;

  if (Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_expected_expression);
    return DeclGroupPtrTy();
  }

  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
      getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);

  // Parse <combiner> expression and then parse initializer if any for each
  // correct type.
  unsigned I = 0, E = ReductionTypes.size();
  for (auto *D : DRD.get()) {
    TentativeParsingAction TPA(*this);
    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
                                    Scope::OpenMPDirectiveScope);
    // Parse <combiner> expression.
    Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
    ExprResult CombinerResult =
        Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
                                    D->getLocation(), /*DiscardedValue=*/true);
    Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());

    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
        Tok.isNot(tok::annot_pragma_openmp_end)) {
      TPA.Commit();
      IsCorrect = false;
      break;
    }
    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
    ExprResult InitializerResult;
    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
      // Parse <initializer> expression.
      if (Tok.is(tok::identifier) &&
          Tok.getIdentifierInfo()->isStr("initializer"))
        ConsumeToken();
      else {
        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
        TPA.Commit();
        IsCorrect = false;
        break;
      }
      // Parse '('.
      BalancedDelimiterTracker T(*this, tok::l_paren,
                                 tok::annot_pragma_openmp_end);
      IsCorrect =
          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
          IsCorrect;
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
                                        Scope::OpenMPDirectiveScope);
        // Parse expression.
        Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
        InitializerResult = Actions.ActOnFinishFullExpr(
            ParseAssignmentExpression().get(), D->getLocation(),
            /*DiscardedValue=*/true);
        Actions.ActOnOpenMPDeclareReductionInitializerEnd(
            D, InitializerResult.get());
        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
            Tok.isNot(tok::annot_pragma_openmp_end)) {
          TPA.Commit();
          IsCorrect = false;
          break;
        }
        IsCorrect =
            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
a79 144

    ++I;
    // Revert parsing if not the last type, otherwise accept it, we're done with
    // parsing.
    if (I != E)
      TPA.Revert();
    else
      TPA.Commit();
  }
  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
                                                         IsCorrect);
}

namespace {
/// RAII that recreates function context for correct parsing of clauses of
/// 'declare simd' construct.
/// OpenMP, 2.8.2 declare simd Construct
/// The expressions appearing in the clauses of this directive are evaluated in
/// the scope of the arguments of the function declaration or definition.
class FNContextRAII final {
  Parser &P;
  Sema::CXXThisScopeRAII *ThisScope;
  Parser::ParseScope *TempScope;
  Parser::ParseScope *FnScope;
  bool HasTemplateScope = false;
  bool HasFunScope = false;
  FNContextRAII() = delete;
  FNContextRAII(const FNContextRAII &) = delete;
  FNContextRAII &operator=(const FNContextRAII &) = delete;

public:
  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
    Decl *D = *Ptr.get().begin();
    NamedDecl *ND = dyn_cast<NamedDecl>(D);
    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
    Sema &Actions = P.getActions();

    // Allow 'this' within late-parsed attributes.
    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
                                           ND && ND->isCXXInstanceMember());

    // If the Decl is templatized, add template parameters to scope.
    HasTemplateScope = D->isTemplateDecl();
    TempScope =
        new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
    if (HasTemplateScope)
      Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);

    // If the Decl is on a function, add function parameters to the scope.
    HasFunScope = D->isFunctionOrFunctionTemplate();
    FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
                                     HasFunScope);
    if (HasFunScope)
      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
  }
  ~FNContextRAII() {
    if (HasFunScope) {
      P.getActions().ActOnExitFunctionContext();
      FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
    }
    if (HasTemplateScope)
      TempScope->Exit();
    delete FnScope;
    delete TempScope;
    delete ThisScope;
  }
};
} // namespace

/// Parses clauses for 'declare simd' directive.
///    clause:
///      'inbranch' | 'notinbranch'
///      'simdlen' '(' <expr> ')'
///      { 'uniform' '(' <argument_list> ')' }
///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
static bool parseDeclareSimdClauses(
    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
  SourceRange BSRange;
  const Token &Tok = P.getCurToken();
  bool IsError = false;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    if (Tok.isNot(tok::identifier))
      break;
    OMPDeclareSimdDeclAttr::BranchStateTy Out;
    IdentifierInfo *II = Tok.getIdentifierInfo();
    StringRef ClauseName = II->getName();
    // Parse 'inranch|notinbranch' clauses.
    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
            << ClauseName
            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
        IsError = true;
      }
      BS = Out;
      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
      P.ConsumeToken();
    } else if (ClauseName.equals("simdlen")) {
      if (SimdLen.isUsable()) {
        P.Diag(Tok, diag::err_omp_more_one_clause)
            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
        IsError = true;
      }
      P.ConsumeToken();
      SourceLocation RLoc;
      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
      if (SimdLen.isInvalid())
        IsError = true;
    } else {
      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
          CKind == OMPC_linear) {
        Parser::OpenMPVarListDataTy Data;
        auto *Vars = &Uniforms;
        if (CKind == OMPC_aligned)
          Vars = &Aligneds;
        else if (CKind == OMPC_linear)
          Vars = &Linears;

        P.ConsumeToken();
        if (P.ParseOpenMPVarList(OMPD_declare_simd,
                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
          IsError = true;
        if (CKind == OMPC_aligned)
          Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
        else if (CKind == OMPC_linear) {
          if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
                                                       Data.DepLinMapLoc))
            Data.LinKind = OMPC_LINEAR_val;
          LinModifiers.append(Linears.size() - LinModifiers.size(),
                              Data.LinKind);
          Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
        }
      } else
        // TODO: add parsing of other clauses.
        break;
    }
    // Skip ',' if any.
    if (Tok.is(tok::comma))
      P.ConsumeToken();
d81 1
a81 40
  return IsError;
}

/// Parse clauses for '#pragma omp declare simd'.
Parser::DeclGroupPtrTy
Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
                                   CachedTokens &Toks, SourceLocation Loc) {
  PP.EnterToken(Tok);
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
  // Consume the previously pushed token.
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);

  FNContextRAII FnContext(*this, Ptr);
  OMPDeclareSimdDeclAttr::BranchStateTy BS =
      OMPDeclareSimdDeclAttr::BS_Undefined;
  ExprResult Simdlen;
  SmallVector<Expr *, 4> Uniforms;
  SmallVector<Expr *, 4> Aligneds;
  SmallVector<Expr *, 4> Alignments;
  SmallVector<Expr *, 4> Linears;
  SmallVector<unsigned, 4> LinModifiers;
  SmallVector<Expr *, 4> Steps;
  bool IsError =
      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
                              Alignments, Linears, LinModifiers, Steps);
  // Need to check for extra tokens.
  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
        << getOpenMPDirectiveName(OMPD_declare_simd);
    while (Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
  }
  // Skip the last annot_pragma_openmp_end.
  SourceLocation EndLoc = ConsumeToken();
  if (!IsError) {
    return Actions.ActOnOpenMPDeclareSimdDirective(
        Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
        LinModifiers, Steps, SourceRange(Loc, EndLoc));
  }
  return Ptr;
a87 1
///         annot_pragma_openmp_end
d89 1
a89 12
///       declare-reduction-directive:
///        annot_pragma_openmp 'declare' 'reduction' [...]
///        annot_pragma_openmp_end
///
///       declare-simd-directive:
///         annot_pragma_openmp 'declare simd' {<clause> [,]}
///         annot_pragma_openmp_end
///         <function declaration/definition>
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
    DeclSpec::TST TagType, Decl *Tag) {
d94 1
d98 1
a98 1
  case OMPD_threadprivate: {
d100 1
a100 2
    ThreadprivateListParserHelper Helper(this);
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
d110 1
a110 2
      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
                                                       Helper.getIdentifiers());
a112 128
  }
  case OMPD_declare_reduction:
    ConsumeToken();
    if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_declare_reduction);
        while (Tok.isNot(tok::annot_pragma_openmp_end))
          ConsumeAnyToken();
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeToken();
      return Res;
    }
    break;
  case OMPD_declare_simd: {
    // The syntax is:
    // { #pragma omp declare simd }
    // <function-declaration-or-definition>
    //
    ConsumeToken();
    CachedTokens Toks;
    while(Tok.isNot(tok::annot_pragma_openmp_end)) {
      Toks.push_back(Tok);
      ConsumeAnyToken();
    }
    Toks.push_back(Tok);
    ConsumeAnyToken();

    DeclGroupPtrTy Ptr;
    if (Tok.is(tok::annot_pragma_openmp))
      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
    else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
      // Here we expect to see some function declaration.
      if (AS == AS_none) {
        assert(TagType == DeclSpec::TST_unspecified);
        MaybeParseCXX11Attributes(Attrs);
        ParsingDeclSpec PDS(*this);
        Ptr = ParseExternalDeclaration(Attrs, &PDS);
      } else {
        Ptr =
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
      }
    }
    if (!Ptr) {
      Diag(Loc, diag::err_omp_decl_in_declare_simd);
      return DeclGroupPtrTy();
    }
    return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
  }
  case OMPD_declare_target: {
    SourceLocation DTLoc = ConsumeAnyToken();
    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
      // OpenMP 4.5 syntax with list of entities.
      llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
      while (Tok.isNot(tok::annot_pragma_openmp_end)) {
        OMPDeclareTargetDeclAttr::MapTypeTy MT =
            OMPDeclareTargetDeclAttr::MT_To;
        if (Tok.is(tok::identifier)) {
          IdentifierInfo *II = Tok.getIdentifierInfo();
          StringRef ClauseName = II->getName();
          // Parse 'to|link' clauses.
          if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
                                                               MT)) {
            Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
                << ClauseName;
            break;
          }
          ConsumeToken();
        }
        auto Callback = [this, MT, &SameDirectiveDecls](
            CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
          Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
                                               SameDirectiveDecls);
        };
        if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
          break;

        // Consume optional ','.
        if (Tok.is(tok::comma))
          ConsumeToken();
      }
      SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      ConsumeAnyToken();
      return DeclGroupPtrTy();
    }

    // Skip the last annot_pragma_openmp_end.
    ConsumeAnyToken();

    if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
      return DeclGroupPtrTy();

    DKind = ParseOpenMPDirectiveKind(*this);
    while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
           Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
      ParsedAttributesWithRange attrs(AttrFactory);
      MaybeParseCXX11Attributes(attrs);
      ParseExternalDeclaration(attrs);
      if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
        TentativeParsingAction TPA(*this);
        ConsumeToken();
        DKind = ParseOpenMPDirectiveKind(*this);
        if (DKind != OMPD_end_declare_target)
          TPA.Revert();
        else
          TPA.Commit();
      }
    }

    if (DKind == OMPD_end_declare_target) {
      ConsumeAnyToken();
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_end_declare_target);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnyToken();
    } else {
      Diag(Tok, diag::err_expected_end_declare_target);
      Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
    }
    Actions.ActOnFinishOpenMPDeclareTargetDirective();
    return DeclGroupPtrTy();
  }
a140 4
  case OMPD_target_enter_data:
  case OMPD_target_exit_data:
  case OMPD_target_parallel:
  case OMPD_target_parallel_for:
a143 16
  case OMPD_end_declare_target:
  case OMPD_target_update:
  case OMPD_distribute_parallel_for:
  case OMPD_distribute_parallel_for_simd:
  case OMPD_distribute_simd:
  case OMPD_target_parallel_for_simd:
  case OMPD_target_simd:
  case OMPD_teams_distribute:
  case OMPD_teams_distribute_simd:
  case OMPD_teams_distribute_parallel_for_simd:
  case OMPD_teams_distribute_parallel_for:
  case OMPD_target_teams:
  case OMPD_target_teams_distribute:
  case OMPD_target_teams_distribute_parallel_for:
  case OMPD_target_teams_distribute_parallel_for_simd:
  case OMPD_target_teams_distribute_simd:
d148 2
a149 4
  while (Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();
  ConsumeAnyToken();
  return nullptr;
a157 6
///       declare-reduction-directive:
///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
///         ('omp_priv' '=' <expression>|<function_call>) ')']
///         annot_pragma_openmp_end
///
d164 2
a165 13
///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
///         'distribute' | 'target enter data' | 'target exit data' |
///         'target parallel' | 'target parallel for' |
///         'target update' | 'distribute parallel for' |
///         'distribute paralle for simd' | 'distribute simd' |
///         'target parallel for simd' | 'target simd' |
///         'teams distribute' | 'teams distribute simd' |
///         'teams distribute parallel for simd' |
///         'teams distribute parallel for' | 'target teams' |
///         'target teams distribute' |
///         'target teams distribute parallel for' |
///         'target teams distribute parallel for simd' |
///         'target teams distribute simd' {clause}
d172 1
d188 1
a188 1
  case OMPD_threadprivate: {
d194 1
a194 2
    ThreadprivateListParserHelper Helper(this);
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
d202 2
a203 2
      DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
          Loc, Helper.getIdentifiers());
a207 17
  }
  case OMPD_declare_reduction:
    ConsumeToken();
    if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_declare_reduction);
        while (Tok.isNot(tok::annot_pragma_openmp_end))
          ConsumeAnyToken();
      }
      ConsumeAnyToken();
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    } else
      SkipUntil(tok::annot_pragma_openmp_end);
    break;
a219 3
  case OMPD_target_enter_data:
  case OMPD_target_exit_data:
  case OMPD_target_update:
a244 2
  case OMPD_target_parallel:
  case OMPD_target_parallel_for:
d247 1
a247 15
  case OMPD_distribute:
  case OMPD_distribute_parallel_for:
  case OMPD_distribute_parallel_for_simd:
  case OMPD_distribute_simd:
  case OMPD_target_parallel_for_simd:
  case OMPD_target_simd:
  case OMPD_teams_distribute:
  case OMPD_teams_distribute_simd:
  case OMPD_teams_distribute_parallel_for_simd:
  case OMPD_teams_distribute_parallel_for:
  case OMPD_target_teams:
  case OMPD_target_teams_distribute:
  case OMPD_target_teams_distribute_parallel_for:
  case OMPD_target_teams_distribute_parallel_for_simd:
  case OMPD_target_teams_distribute_simd: {
a333 7
  case OMPD_declare_simd:
  case OMPD_declare_target:
  case OMPD_end_declare_target:
    Diag(Tok, diag::err_omp_unexpected_directive)
        << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
d342 10
a351 9
// Parses simple list:
//   simple-variable-list:
//         '(' id-expression {, id-expression} ')'
//
bool Parser::ParseOpenMPSimpleVarList(
    OpenMPDirectiveKind Kind,
    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
        Callback,
    bool AllowScopeSpecifier) {
d370 1
a370 1
        ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
d374 1
a374 1
    } else if (ParseUnqualifiedId(SS, false, false, false, nullptr,
d388 5
a392 1
      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
d408 1
a408 1
  return !IsCorrect;
d423 1
a423 2
///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
///       from-clause | is_device_ptr-clause
a496 2
  case OMPC_dist_schedule:
  case OMPC_defaultmap:
a498 2
    // OpenMP [2.10.4, Restrictions, p. 106]
    //  At most one defaultmap clause can appear on the directive.
a542 4
  case OMPC_to:
  case OMPC_from:
  case OMPC_use_device_ptr:
  case OMPC_is_device_ptr:
a550 1
  case OMPC_uniform:
a558 22
/// Parses simple expression in parens for single-expression clauses of OpenMP
/// constructs.
/// \param RLoc Returned location of right paren.
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
                                         SourceLocation &RLoc) {
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
    return ExprError();

  SourceLocation ELoc = Tok.getLocation();
  ExprResult LHS(ParseCastExpression(
      /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);

  // Parse ')'.
  T.consumeClose();

  RLoc = T.getCloseLocation();
  return Val;
}

a591 2
  SourceLocation LLoc = Tok.getLocation();
  SourceLocation RLoc;
d593 12
a604 1
  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
d609 2
a610 1
  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
a687 3
///    defaultmap:
///      'defaultmap' '(' modifier ':' kind ')'
///
a746 29
  } else if (Kind == OMPC_dist_schedule) {
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
      DelimLoc = ConsumeAnyToken();
  } else if (Kind == OMPC_defaultmap) {
    // Get a defaultmap modifier
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    // Parse ':'
    if (Tok.is(tok::colon))
      ConsumeAnyToken();
    else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
      Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
    // Get a defaultmap kind
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
a749 1
    TentativeParsingAction TPA(*this);
d753 1
a753 2
      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
        TPA.Commit();
d755 4
a758 6
      } else {
        TPA.Revert();
        Arg.back() = OMPD_unknown;
      }
    } else
      TPA.Revert();
d761 2
a762 3
  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
                          (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
                          Kind == OMPC_if;
d823 1
a823 1
                              /*AllowConstructorName*/ false, nullptr,
d827 39
a865 6
/// Parses clauses with list.
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
                                OpenMPClauseKind Kind,
                                SmallVectorImpl<Expr *> &Vars,
                                OpenMPVarListDataTy &Data) {
  UnqualifiedId UnqualifiedReductionId;
d867 6
d874 2
d881 1
a881 1
    return true;
d889 5
a893 6
    if (getLangOpts().CPlusPlus)
      ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
                                     /*ObjectType=*/nullptr,
                                     /*EnteringContext=*/false);
    InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
                                          UnqualifiedReductionId);
d898 3
a900 3
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else
d902 1
a902 3
    if (!InvalidReductionId)
      Data.ReductionId =
          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
d906 3
a908 4
    Data.DepKind =
        static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
            Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
    Data.DepLinMapLoc = Tok.getLocation();
d910 1
a910 1
    if (Data.DepKind == OMPC_DEPEND_unknown) {
d916 1
a916 1
      if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
d919 5
a923 1
        return false;
d926 3
a928 3
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else {
d936 1
a936 1
      Data.LinKind = static_cast<OpenMPLinearClauseKind>(
d938 1
a938 1
      Data.DepLinMapLoc = ConsumeToken();
d946 5
a950 15
    /// The map clause modifier token can be either a identifier or the C++
    /// delete keyword.
    auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
      return Tok.isOneOf(tok::identifier, tok::kw_delete);
    };

    // The first identifier may be a list item, a map-type or a
    // map-type-modifier. The map modifier can also be delete which has the same
    // spelling of the C++ delete keyword.
    Data.MapType =
        IsMapClauseModifierToken(Tok)
            ? static_cast<OpenMPMapClauseKind>(
                  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
            : OMPC_MAP_unknown;
    Data.DepLinMapLoc = Tok.getLocation();
d953 1
a953 1
    if (IsMapClauseModifierToken(Tok)) {
d955 3
a957 1
        if (Data.MapType == OMPC_MAP_unknown)
d959 1
a959 1
        else if (Data.MapType == OMPC_MAP_always)
d961 1
d964 1
a964 1
        if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
d966 4
a969 2
          Data.MapTypeModifier = Data.MapType;
          if (Data.MapTypeModifier != OMPC_MAP_always) {
d971 2
a972 2
            Data.MapTypeModifier = OMPC_MAP_unknown;
          } else
d974 1
d979 3
a981 7
          Data.MapType =
              IsMapClauseModifierToken(Tok)
                  ? static_cast<OpenMPMapClauseKind>(
                        getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
                  : OMPC_MAP_unknown;
          if (Data.MapType == OMPC_MAP_unknown ||
              Data.MapType == OMPC_MAP_always)
d983 1
d986 1
a986 2
          Data.MapType = OMPC_MAP_tofrom;
          Data.IsMapTypeImplicit = true;
d989 1
a989 2
        Data.MapType = OMPC_MAP_tofrom;
        Data.IsMapTypeImplicit = true;
d992 1
a992 2
      Data.MapType = OMPC_MAP_tofrom;
      Data.IsMapTypeImplicit = true;
d995 3
a997 3
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else if (ColonExpected)
d999 1
d1002 1
d1004 4
a1007 3
      (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
      (Kind == OMPC_reduction && !InvalidReductionId) ||
      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
d1009 2
a1010 2
        Data.MapTypeModifier == OMPC_MAP_always)) ||
      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
d1018 1
a1018 1
    if (VarExpr.isUsable())
d1020 1
a1020 1
    else {
d1042 1
d1045 1
a1045 1
    Data.ColonLoc = Tok.getLocation();
d1050 1
a1050 1
      Data.TailExpr = Tail.get();
d1058 4
a1061 55
  if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
       Vars.empty()) ||
      (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
      (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
    return true;
  return false;
}

/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' linear-list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///    depend-clause:
///       'depend' '(' in | out | inout : list | source ')'
///    map-clause:
///       'map' '(' [ [ always , ]
///          to | from | tofrom | alloc | release | delete ':' ] list ')';
///    to-clause:
///       'to' '(' list ')'
///    from-clause:
///       'from' '(' list ')'
///    use_device_ptr-clause:
///       'use_device_ptr' '(' list ')'
///    is_device_ptr-clause:
///       'is_device_ptr' '(' list ')'
///
/// For 'linear' clause linear-list may have the following forms:
///  list
///  modifier(list)
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
                                            OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  SmallVector<Expr *, 4> Vars;
  OpenMPVarListDataTy Data;

  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
d1063 1
d1066 5
a1070 4
      Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
      Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
      Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
      Data.DepLinMapLoc);
@


1.1.1.10
log
@Import Clang pre-4.0.0 r291444.
@
text
@d15 1
a28 55
namespace {
enum OpenMPDirectiveKindEx {
  OMPD_cancellation = OMPD_unknown + 1,
  OMPD_data,
  OMPD_declare,
  OMPD_end,
  OMPD_end_declare,
  OMPD_enter,
  OMPD_exit,
  OMPD_point,
  OMPD_reduction,
  OMPD_target_enter,
  OMPD_target_exit,
  OMPD_update,
  OMPD_distribute_parallel,
  OMPD_teams_distribute_parallel,
  OMPD_target_teams_distribute_parallel
};

class ThreadprivateListParserHelper final {
  SmallVector<Expr *, 4> Identifiers;
  Parser *P;

public:
  ThreadprivateListParserHelper(Parser *P) : P(P) {}
  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
    ExprResult Res =
        P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
    if (Res.isUsable())
      Identifiers.push_back(Res.get());
  }
  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
};
} // namespace

// Map token string to extended OMP token kind that are
// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
static unsigned getOpenMPDirectiveKindEx(StringRef S) {
  auto DKind = getOpenMPDirectiveKind(S);
  if (DKind != OMPD_unknown)
    return DKind;

  return llvm::StringSwitch<unsigned>(S)
      .Case("cancellation", OMPD_cancellation)
      .Case("data", OMPD_data)
      .Case("declare", OMPD_declare)
      .Case("end", OMPD_end)
      .Case("enter", OMPD_enter)
      .Case("exit", OMPD_exit)
      .Case("point", OMPD_point)
      .Case("reduction", OMPD_reduction)
      .Case("update", OMPD_update)
      .Default(OMPD_unknown);
}

d33 9
a41 39
  static const unsigned F[][3] = {
    { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
    { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
    { OMPD_declare, OMPD_simd, OMPD_declare_simd },
    { OMPD_declare, OMPD_target, OMPD_declare_target },
    { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
    { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
    { OMPD_distribute_parallel_for, OMPD_simd, 
      OMPD_distribute_parallel_for_simd },
    { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
    { OMPD_end, OMPD_declare, OMPD_end_declare },
    { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
    { OMPD_target, OMPD_data, OMPD_target_data },
    { OMPD_target, OMPD_enter, OMPD_target_enter },
    { OMPD_target, OMPD_exit, OMPD_target_exit },
    { OMPD_target, OMPD_update, OMPD_target_update },
    { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
    { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
    { OMPD_for, OMPD_simd, OMPD_for_simd },
    { OMPD_parallel, OMPD_for, OMPD_parallel_for },
    { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
    { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
    { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
    { OMPD_target, OMPD_parallel, OMPD_target_parallel },
    { OMPD_target, OMPD_simd, OMPD_target_simd },
    { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
    { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
    { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
    { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
    { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
    { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
    { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
    { OMPD_target, OMPD_teams, OMPD_target_teams },
    { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
    { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
    { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
    { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
  };
  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
d43 1
a43 1
  unsigned DKind =
d45 2
a46 4
          ? static_cast<unsigned>(OMPD_unknown)
          : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
  if (DKind == OMPD_unknown)
    return OMPD_unknown;
d48 1
d50 4
a53 124
    if (DKind != F[i][0])
      continue;

    Tok = P.getPreprocessor().LookAhead(0);
    unsigned SDKind =
        Tok.isAnnotation()
            ? static_cast<unsigned>(OMPD_unknown)
            : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
    if (SDKind == OMPD_unknown)
      continue;

    if (SDKind == F[i][1]) {
      P.ConsumeToken();
      DKind = F[i][2];
    }
  }
  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
                              : OMPD_unknown;
}

static DeclarationName parseOpenMPReductionId(Parser &P) {
  Token Tok = P.getCurToken();
  Sema &Actions = P.getActions();
  OverloadedOperatorKind OOK = OO_None;
  // Allow to use 'operator' keyword for C++ operators
  bool WithOperator = false;
  if (Tok.is(tok::kw_operator)) {
    P.ConsumeToken();
    Tok = P.getCurToken();
    WithOperator = true;
  }
  switch (Tok.getKind()) {
  case tok::plus: // '+'
    OOK = OO_Plus;
    break;
  case tok::minus: // '-'
    OOK = OO_Minus;
    break;
  case tok::star: // '*'
    OOK = OO_Star;
    break;
  case tok::amp: // '&'
    OOK = OO_Amp;
    break;
  case tok::pipe: // '|'
    OOK = OO_Pipe;
    break;
  case tok::caret: // '^'
    OOK = OO_Caret;
    break;
  case tok::ampamp: // '&&'
    OOK = OO_AmpAmp;
    break;
  case tok::pipepipe: // '||'
    OOK = OO_PipePipe;
    break;
  case tok::identifier: // identifier
    if (!WithOperator)
      break;
  default:
    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                Parser::StopBeforeMatch);
    return DeclarationName();
  }
  P.ConsumeToken();
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
                        : DeclNames.getCXXOperatorName(OOK);
}

/// \brief Parse 'omp declare reduction' construct.
///
///       declare-reduction-directive:
///        annot_pragma_openmp 'declare' 'reduction'
///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
///        annot_pragma_openmp_end
/// <reduction_id> is either a base language identifier or one of the following
/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
///
Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPDirectiveName(OMPD_declare_reduction))) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  DeclarationName Name = parseOpenMPReductionId(*this);
  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Consume ':'.
  bool IsCorrect = !ExpectAndConsume(tok::colon);

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  IsCorrect = IsCorrect && !Name.isEmpty();

  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_expected_type);
    IsCorrect = false;
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
  // Parse list of types until ':' token.
  do {
    ColonProtectionRAIIObject ColonRAII(*this);
    SourceRange Range;
    TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
    if (TR.isUsable()) {
      auto ReductionType =
          Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
      if (!ReductionType.isNull()) {
        ReductionTypes.push_back(
            std::make_pair(ReductionType, Range.getBegin()));
      }
d55 1
a55 2
      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
d58 15
a72 9
    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
      break;

    // Consume ','.
    if (ExpectAndConsume(tok::comma)) {
      IsCorrect = false;
      if (Tok.is(tok::annot_pragma_openmp_end)) {
        Diag(Tok.getLocation(), diag::err_expected_type);
        return DeclGroupPtrTy();
a73 2
    }
  } while (Tok.isNot(tok::annot_pragma_openmp_end));
d75 3
a77 77
  if (ReductionTypes.empty()) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Consume ':'.
  if (ExpectAndConsume(tok::colon))
    IsCorrect = false;

  if (Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_expected_expression);
    return DeclGroupPtrTy();
  }

  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
      getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);

  // Parse <combiner> expression and then parse initializer if any for each
  // correct type.
  unsigned I = 0, E = ReductionTypes.size();
  for (auto *D : DRD.get()) {
    TentativeParsingAction TPA(*this);
    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
                                    Scope::OpenMPDirectiveScope);
    // Parse <combiner> expression.
    Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
    ExprResult CombinerResult =
        Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
                                    D->getLocation(), /*DiscardedValue=*/true);
    Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());

    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
        Tok.isNot(tok::annot_pragma_openmp_end)) {
      TPA.Commit();
      IsCorrect = false;
      break;
    }
    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
    ExprResult InitializerResult;
    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
      // Parse <initializer> expression.
      if (Tok.is(tok::identifier) &&
          Tok.getIdentifierInfo()->isStr("initializer"))
        ConsumeToken();
      else {
        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
        TPA.Commit();
        IsCorrect = false;
        break;
      }
      // Parse '('.
      BalancedDelimiterTracker T(*this, tok::l_paren,
                                 tok::annot_pragma_openmp_end);
      IsCorrect =
          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
          IsCorrect;
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
                                        Scope::OpenMPDirectiveScope);
        // Parse expression.
        Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
        InitializerResult = Actions.ActOnFinishFullExpr(
            ParseAssignmentExpression().get(), D->getLocation(),
            /*DiscardedValue=*/true);
        Actions.ActOnOpenMPDeclareReductionInitializerEnd(
            D, InitializerResult.get());
        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
            Tok.isNot(tok::annot_pragma_openmp_end)) {
          TPA.Commit();
          IsCorrect = false;
          break;
        }
        IsCorrect =
            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
a79 144

    ++I;
    // Revert parsing if not the last type, otherwise accept it, we're done with
    // parsing.
    if (I != E)
      TPA.Revert();
    else
      TPA.Commit();
  }
  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
                                                         IsCorrect);
}

namespace {
/// RAII that recreates function context for correct parsing of clauses of
/// 'declare simd' construct.
/// OpenMP, 2.8.2 declare simd Construct
/// The expressions appearing in the clauses of this directive are evaluated in
/// the scope of the arguments of the function declaration or definition.
class FNContextRAII final {
  Parser &P;
  Sema::CXXThisScopeRAII *ThisScope;
  Parser::ParseScope *TempScope;
  Parser::ParseScope *FnScope;
  bool HasTemplateScope = false;
  bool HasFunScope = false;
  FNContextRAII() = delete;
  FNContextRAII(const FNContextRAII &) = delete;
  FNContextRAII &operator=(const FNContextRAII &) = delete;

public:
  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
    Decl *D = *Ptr.get().begin();
    NamedDecl *ND = dyn_cast<NamedDecl>(D);
    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
    Sema &Actions = P.getActions();

    // Allow 'this' within late-parsed attributes.
    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
                                           ND && ND->isCXXInstanceMember());

    // If the Decl is templatized, add template parameters to scope.
    HasTemplateScope = D->isTemplateDecl();
    TempScope =
        new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
    if (HasTemplateScope)
      Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);

    // If the Decl is on a function, add function parameters to the scope.
    HasFunScope = D->isFunctionOrFunctionTemplate();
    FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
                                     HasFunScope);
    if (HasFunScope)
      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
  }
  ~FNContextRAII() {
    if (HasFunScope) {
      P.getActions().ActOnExitFunctionContext();
      FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
    }
    if (HasTemplateScope)
      TempScope->Exit();
    delete FnScope;
    delete TempScope;
    delete ThisScope;
  }
};
} // namespace

/// Parses clauses for 'declare simd' directive.
///    clause:
///      'inbranch' | 'notinbranch'
///      'simdlen' '(' <expr> ')'
///      { 'uniform' '(' <argument_list> ')' }
///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
static bool parseDeclareSimdClauses(
    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
  SourceRange BSRange;
  const Token &Tok = P.getCurToken();
  bool IsError = false;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    if (Tok.isNot(tok::identifier))
      break;
    OMPDeclareSimdDeclAttr::BranchStateTy Out;
    IdentifierInfo *II = Tok.getIdentifierInfo();
    StringRef ClauseName = II->getName();
    // Parse 'inranch|notinbranch' clauses.
    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
            << ClauseName
            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
        IsError = true;
      }
      BS = Out;
      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
      P.ConsumeToken();
    } else if (ClauseName.equals("simdlen")) {
      if (SimdLen.isUsable()) {
        P.Diag(Tok, diag::err_omp_more_one_clause)
            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
        IsError = true;
      }
      P.ConsumeToken();
      SourceLocation RLoc;
      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
      if (SimdLen.isInvalid())
        IsError = true;
    } else {
      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
          CKind == OMPC_linear) {
        Parser::OpenMPVarListDataTy Data;
        auto *Vars = &Uniforms;
        if (CKind == OMPC_aligned)
          Vars = &Aligneds;
        else if (CKind == OMPC_linear)
          Vars = &Linears;

        P.ConsumeToken();
        if (P.ParseOpenMPVarList(OMPD_declare_simd,
                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
          IsError = true;
        if (CKind == OMPC_aligned)
          Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
        else if (CKind == OMPC_linear) {
          if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
                                                       Data.DepLinMapLoc))
            Data.LinKind = OMPC_LINEAR_val;
          LinModifiers.append(Linears.size() - LinModifiers.size(),
                              Data.LinKind);
          Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
        }
      } else
        // TODO: add parsing of other clauses.
        break;
    }
    // Skip ',' if any.
    if (Tok.is(tok::comma))
      P.ConsumeToken();
d81 1
a81 40
  return IsError;
}

/// Parse clauses for '#pragma omp declare simd'.
Parser::DeclGroupPtrTy
Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
                                   CachedTokens &Toks, SourceLocation Loc) {
  PP.EnterToken(Tok);
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
  // Consume the previously pushed token.
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);

  FNContextRAII FnContext(*this, Ptr);
  OMPDeclareSimdDeclAttr::BranchStateTy BS =
      OMPDeclareSimdDeclAttr::BS_Undefined;
  ExprResult Simdlen;
  SmallVector<Expr *, 4> Uniforms;
  SmallVector<Expr *, 4> Aligneds;
  SmallVector<Expr *, 4> Alignments;
  SmallVector<Expr *, 4> Linears;
  SmallVector<unsigned, 4> LinModifiers;
  SmallVector<Expr *, 4> Steps;
  bool IsError =
      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
                              Alignments, Linears, LinModifiers, Steps);
  // Need to check for extra tokens.
  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
        << getOpenMPDirectiveName(OMPD_declare_simd);
    while (Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
  }
  // Skip the last annot_pragma_openmp_end.
  SourceLocation EndLoc = ConsumeToken();
  if (!IsError) {
    return Actions.ActOnOpenMPDeclareSimdDirective(
        Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
        LinModifiers, Steps, SourceRange(Loc, EndLoc));
  }
  return Ptr;
a87 1
///         annot_pragma_openmp_end
d89 1
a89 12
///       declare-reduction-directive:
///        annot_pragma_openmp 'declare' 'reduction' [...]
///        annot_pragma_openmp_end
///
///       declare-simd-directive:
///         annot_pragma_openmp 'declare simd' {<clause> [,]}
///         annot_pragma_openmp_end
///         <function declaration/definition>
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
    DeclSpec::TST TagType, Decl *Tag) {
d94 1
d98 1
a98 1
  case OMPD_threadprivate: {
d100 1
a100 2
    ThreadprivateListParserHelper Helper(this);
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
d110 1
a110 2
      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
                                                       Helper.getIdentifiers());
a112 128
  }
  case OMPD_declare_reduction:
    ConsumeToken();
    if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_declare_reduction);
        while (Tok.isNot(tok::annot_pragma_openmp_end))
          ConsumeAnyToken();
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeToken();
      return Res;
    }
    break;
  case OMPD_declare_simd: {
    // The syntax is:
    // { #pragma omp declare simd }
    // <function-declaration-or-definition>
    //
    ConsumeToken();
    CachedTokens Toks;
    while(Tok.isNot(tok::annot_pragma_openmp_end)) {
      Toks.push_back(Tok);
      ConsumeAnyToken();
    }
    Toks.push_back(Tok);
    ConsumeAnyToken();

    DeclGroupPtrTy Ptr;
    if (Tok.is(tok::annot_pragma_openmp))
      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
    else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
      // Here we expect to see some function declaration.
      if (AS == AS_none) {
        assert(TagType == DeclSpec::TST_unspecified);
        MaybeParseCXX11Attributes(Attrs);
        ParsingDeclSpec PDS(*this);
        Ptr = ParseExternalDeclaration(Attrs, &PDS);
      } else {
        Ptr =
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
      }
    }
    if (!Ptr) {
      Diag(Loc, diag::err_omp_decl_in_declare_simd);
      return DeclGroupPtrTy();
    }
    return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
  }
  case OMPD_declare_target: {
    SourceLocation DTLoc = ConsumeAnyToken();
    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
      // OpenMP 4.5 syntax with list of entities.
      llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
      while (Tok.isNot(tok::annot_pragma_openmp_end)) {
        OMPDeclareTargetDeclAttr::MapTypeTy MT =
            OMPDeclareTargetDeclAttr::MT_To;
        if (Tok.is(tok::identifier)) {
          IdentifierInfo *II = Tok.getIdentifierInfo();
          StringRef ClauseName = II->getName();
          // Parse 'to|link' clauses.
          if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
                                                               MT)) {
            Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
                << ClauseName;
            break;
          }
          ConsumeToken();
        }
        auto Callback = [this, MT, &SameDirectiveDecls](
            CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
          Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
                                               SameDirectiveDecls);
        };
        if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
          break;

        // Consume optional ','.
        if (Tok.is(tok::comma))
          ConsumeToken();
      }
      SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      ConsumeAnyToken();
      return DeclGroupPtrTy();
    }

    // Skip the last annot_pragma_openmp_end.
    ConsumeAnyToken();

    if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
      return DeclGroupPtrTy();

    DKind = ParseOpenMPDirectiveKind(*this);
    while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
           Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
      ParsedAttributesWithRange attrs(AttrFactory);
      MaybeParseCXX11Attributes(attrs);
      ParseExternalDeclaration(attrs);
      if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
        TentativeParsingAction TPA(*this);
        ConsumeToken();
        DKind = ParseOpenMPDirectiveKind(*this);
        if (DKind != OMPD_end_declare_target)
          TPA.Revert();
        else
          TPA.Commit();
      }
    }

    if (DKind == OMPD_end_declare_target) {
      ConsumeAnyToken();
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_end_declare_target);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnyToken();
    } else {
      Diag(Tok, diag::err_expected_end_declare_target);
      Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
    }
    Actions.ActOnFinishOpenMPDeclareTargetDirective();
    return DeclGroupPtrTy();
  }
a140 4
  case OMPD_target_enter_data:
  case OMPD_target_exit_data:
  case OMPD_target_parallel:
  case OMPD_target_parallel_for:
a143 15
  case OMPD_end_declare_target:
  case OMPD_target_update:
  case OMPD_distribute_parallel_for:
  case OMPD_distribute_parallel_for_simd:
  case OMPD_distribute_simd:
  case OMPD_target_parallel_for_simd:
  case OMPD_target_simd:
  case OMPD_teams_distribute:
  case OMPD_teams_distribute_simd:
  case OMPD_teams_distribute_parallel_for_simd:
  case OMPD_teams_distribute_parallel_for:
  case OMPD_target_teams:
  case OMPD_target_teams_distribute:
  case OMPD_target_teams_distribute_parallel_for:
  case OMPD_target_teams_distribute_parallel_for_simd:
d148 2
a149 4
  while (Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();
  ConsumeAnyToken();
  return nullptr;
a157 6
///       declare-reduction-directive:
///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
///         ('omp_priv' '=' <expression>|<function_call>) ')']
///         annot_pragma_openmp_end
///
d164 2
a165 12
///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
///         'distribute' | 'target enter data' | 'target exit data' |
///         'target parallel' | 'target parallel for' |
///         'target update' | 'distribute parallel for' |
///         'distribute paralle for simd' | 'distribute simd' |
///         'target parallel for simd' | 'target simd' |
///         'teams distribute' | 'teams distribute simd' |
///         'teams distribute parallel for simd' |
///         'teams distribute parallel for' | 'target teams' |
///         'target teams distribute' |
///         'target teams distribute parallel for' |
///         'target teams distribute parallel for simd' {clause}
d172 1
d188 1
a188 1
  case OMPD_threadprivate: {
d194 1
a194 2
    ThreadprivateListParserHelper Helper(this);
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
d202 2
a203 2
      DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
          Loc, Helper.getIdentifiers());
a207 17
  }
  case OMPD_declare_reduction:
    ConsumeToken();
    if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_declare_reduction);
        while (Tok.isNot(tok::annot_pragma_openmp_end))
          ConsumeAnyToken();
      }
      ConsumeAnyToken();
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    } else
      SkipUntil(tok::annot_pragma_openmp_end);
    break;
a219 3
  case OMPD_target_enter_data:
  case OMPD_target_exit_data:
  case OMPD_target_update:
a244 2
  case OMPD_target_parallel:
  case OMPD_target_parallel_for:
d247 1
a247 14
  case OMPD_distribute:
  case OMPD_distribute_parallel_for:
  case OMPD_distribute_parallel_for_simd:
  case OMPD_distribute_simd:
  case OMPD_target_parallel_for_simd:
  case OMPD_target_simd:
  case OMPD_teams_distribute:
  case OMPD_teams_distribute_simd:
  case OMPD_teams_distribute_parallel_for_simd:
  case OMPD_teams_distribute_parallel_for:
  case OMPD_target_teams:
  case OMPD_target_teams_distribute:
  case OMPD_target_teams_distribute_parallel_for:
  case OMPD_target_teams_distribute_parallel_for_simd: {
a333 7
  case OMPD_declare_simd:
  case OMPD_declare_target:
  case OMPD_end_declare_target:
    Diag(Tok, diag::err_omp_unexpected_directive)
        << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
d342 10
a351 9
// Parses simple list:
//   simple-variable-list:
//         '(' id-expression {, id-expression} ')'
//
bool Parser::ParseOpenMPSimpleVarList(
    OpenMPDirectiveKind Kind,
    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
        Callback,
    bool AllowScopeSpecifier) {
d370 1
a370 1
        ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
d374 1
a374 1
    } else if (ParseUnqualifiedId(SS, false, false, false, nullptr,
d388 5
a392 1
      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
d408 1
a408 1
  return !IsCorrect;
d423 1
a423 2
///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
///       from-clause | is_device_ptr-clause
a496 2
  case OMPC_dist_schedule:
  case OMPC_defaultmap:
a498 2
    // OpenMP [2.10.4, Restrictions, p. 106]
    //  At most one defaultmap clause can appear on the directive.
a542 4
  case OMPC_to:
  case OMPC_from:
  case OMPC_use_device_ptr:
  case OMPC_is_device_ptr:
a550 1
  case OMPC_uniform:
a558 22
/// Parses simple expression in parens for single-expression clauses of OpenMP
/// constructs.
/// \param RLoc Returned location of right paren.
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
                                         SourceLocation &RLoc) {
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
    return ExprError();

  SourceLocation ELoc = Tok.getLocation();
  ExprResult LHS(ParseCastExpression(
      /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);

  // Parse ')'.
  T.consumeClose();

  RLoc = T.getCloseLocation();
  return Val;
}

a591 2
  SourceLocation LLoc = Tok.getLocation();
  SourceLocation RLoc;
d593 12
a604 1
  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
d609 2
a610 1
  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
a687 3
///    defaultmap:
///      'defaultmap' '(' modifier ':' kind ')'
///
a746 29
  } else if (Kind == OMPC_dist_schedule) {
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
      DelimLoc = ConsumeAnyToken();
  } else if (Kind == OMPC_defaultmap) {
    // Get a defaultmap modifier
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    // Parse ':'
    if (Tok.is(tok::colon))
      ConsumeAnyToken();
    else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
      Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
    // Get a defaultmap kind
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
a749 1
    TentativeParsingAction TPA(*this);
d753 1
a753 2
      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
        TPA.Commit();
d755 4
a758 6
      } else {
        TPA.Revert();
        Arg.back() = OMPD_unknown;
      }
    } else
      TPA.Revert();
d761 2
a762 3
  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
                          (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
                          Kind == OMPC_if;
d823 1
a823 1
                              /*AllowConstructorName*/ false, nullptr,
d827 39
a865 6
/// Parses clauses with list.
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
                                OpenMPClauseKind Kind,
                                SmallVectorImpl<Expr *> &Vars,
                                OpenMPVarListDataTy &Data) {
  UnqualifiedId UnqualifiedReductionId;
d867 6
d874 2
d881 1
a881 1
    return true;
d889 5
a893 6
    if (getLangOpts().CPlusPlus)
      ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
                                     /*ObjectType=*/nullptr,
                                     /*EnteringContext=*/false);
    InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
                                          UnqualifiedReductionId);
d898 3
a900 3
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else
d902 1
a902 3
    if (!InvalidReductionId)
      Data.ReductionId =
          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
d906 3
a908 4
    Data.DepKind =
        static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
            Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
    Data.DepLinMapLoc = Tok.getLocation();
d910 1
a910 1
    if (Data.DepKind == OMPC_DEPEND_unknown) {
d916 1
a916 1
      if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
d919 5
a923 1
        return false;
d926 3
a928 3
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else {
d936 1
a936 1
      Data.LinKind = static_cast<OpenMPLinearClauseKind>(
d938 1
a938 1
      Data.DepLinMapLoc = ConsumeToken();
d946 5
a950 15
    /// The map clause modifier token can be either a identifier or the C++
    /// delete keyword.
    auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
      return Tok.isOneOf(tok::identifier, tok::kw_delete);
    };

    // The first identifier may be a list item, a map-type or a
    // map-type-modifier. The map modifier can also be delete which has the same
    // spelling of the C++ delete keyword.
    Data.MapType =
        IsMapClauseModifierToken(Tok)
            ? static_cast<OpenMPMapClauseKind>(
                  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
            : OMPC_MAP_unknown;
    Data.DepLinMapLoc = Tok.getLocation();
d953 1
a953 1
    if (IsMapClauseModifierToken(Tok)) {
d955 3
a957 1
        if (Data.MapType == OMPC_MAP_unknown)
d959 1
a959 1
        else if (Data.MapType == OMPC_MAP_always)
d961 1
d964 1
a964 1
        if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
d966 4
a969 2
          Data.MapTypeModifier = Data.MapType;
          if (Data.MapTypeModifier != OMPC_MAP_always) {
d971 2
a972 2
            Data.MapTypeModifier = OMPC_MAP_unknown;
          } else
d974 1
d979 3
a981 7
          Data.MapType =
              IsMapClauseModifierToken(Tok)
                  ? static_cast<OpenMPMapClauseKind>(
                        getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
                  : OMPC_MAP_unknown;
          if (Data.MapType == OMPC_MAP_unknown ||
              Data.MapType == OMPC_MAP_always)
d983 1
d986 1
a986 2
          Data.MapType = OMPC_MAP_tofrom;
          Data.IsMapTypeImplicit = true;
d989 1
a989 2
        Data.MapType = OMPC_MAP_tofrom;
        Data.IsMapTypeImplicit = true;
d992 1
a992 2
      Data.MapType = OMPC_MAP_tofrom;
      Data.IsMapTypeImplicit = true;
d995 3
a997 3
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else if (ColonExpected)
d999 1
d1002 1
d1004 4
a1007 3
      (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
      (Kind == OMPC_reduction && !InvalidReductionId) ||
      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
d1009 2
a1010 2
        Data.MapTypeModifier == OMPC_MAP_always)) ||
      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
d1018 1
a1018 1
    if (VarExpr.isUsable())
d1020 1
a1020 1
    else {
d1042 1
d1045 1
a1045 1
    Data.ColonLoc = Tok.getLocation();
d1050 1
a1050 1
      Data.TailExpr = Tail.get();
d1058 4
a1061 55
  if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
       Vars.empty()) ||
      (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
      (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
    return true;
  return false;
}

/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' linear-list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///    depend-clause:
///       'depend' '(' in | out | inout : list | source ')'
///    map-clause:
///       'map' '(' [ [ always , ]
///          to | from | tofrom | alloc | release | delete ':' ] list ')';
///    to-clause:
///       'to' '(' list ')'
///    from-clause:
///       'from' '(' list ')'
///    use_device_ptr-clause:
///       'use_device_ptr' '(' list ')'
///    is_device_ptr-clause:
///       'is_device_ptr' '(' list ')'
///
/// For 'linear' clause linear-list may have the following forms:
///  list
///  modifier(list)
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
                                            OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  SmallVector<Expr *, 4> Vars;
  OpenMPVarListDataTy Data;

  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
d1063 1
d1066 5
a1070 4
      Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
      Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
      Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
      Data.DepLinMapLoc);
@


1.1.1.10.2.1
log
@Sync with HEAD
@
text
@a121 1
    { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
a762 1
  case OMPD_target_teams_distribute_simd:
d802 1
a802 2
///         'target teams distribute parallel for simd' |
///         'target teams distribute simd' {clause}
d919 1
a919 2
  case OMPD_target_teams_distribute_parallel_for_simd:
  case OMPD_target_teams_distribute_simd: {
@


1.1.1.11
log
@Import Clang 4.0RC1 r294123.
@
text
@a121 1
    { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
a762 1
  case OMPD_target_teams_distribute_simd:
d802 1
a802 2
///         'target teams distribute parallel for simd' |
///         'target teams distribute simd' {clause}
d919 1
a919 2
  case OMPD_target_teams_distribute_parallel_for_simd:
  case OMPD_target_teams_distribute_simd: {
@


1.1.1.12
log
@Import clang r309604 from branches/release_50
@
text
@d14 1
a18 1
#include "clang/Parse/RAIIObjectsForParser.h"
a194 1
    LLVM_FALLTHROUGH;
d535 1
a535 1
  SourceLocation EndLoc = ConsumeAnnotationToken();
d565 1
a565 1
  SourceLocation Loc = ConsumeAnnotationToken();
d581 1
a581 1
      ConsumeAnnotationToken();
d599 1
a599 1
      ConsumeAnnotationToken();
d689 1
a689 1
        ConsumeAnnotationToken();
d809 1
a809 1
    AllowedConstructsKind Allowed) {
d817 1
a817 1
  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
a871 1
    LLVM_FALLTHROUGH;
a885 1
    LLVM_FALLTHROUGH;
d976 1
a976 1
    ConsumeAnnotationToken();
d1056 1
a1056 1
    } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
d1102 1
a1102 1
///       from-clause | is_device_ptr-clause | task_reduction-clause
a1186 1
    LLVM_FALLTHROUGH;
a1218 1
  case OMPC_task_reduction:
d1560 2
a1561 3
                              /*AllowConstructorName*/ false,
                              /*AllowDeductionGuide*/ false,
                              nullptr, TemplateKWLoc, ReductionId);
d1583 1
a1583 1
  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
a1691 24
      } else if (IsMapClauseModifierToken(PP.LookAhead(0))) {
        if (PP.LookAhead(1).is(tok::colon)) {
          Data.MapTypeModifier = Data.MapType;
          if (Data.MapTypeModifier != OMPC_MAP_always) {
            Diag(Tok, diag::err_omp_unknown_map_type_modifier);
            Data.MapTypeModifier = OMPC_MAP_unknown;
          } else
            MapTypeModifierSpecified = true;

          ConsumeToken();

          Data.MapType =
              IsMapClauseModifierToken(Tok)
                  ? static_cast<OpenMPMapClauseKind>(
                        getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
                  : OMPC_MAP_unknown;
          if (Data.MapType == OMPC_MAP_unknown ||
              Data.MapType == OMPC_MAP_always)
            Diag(Tok, diag::err_omp_unknown_map_type);
          ConsumeToken();
        } else {
          Data.MapType = OMPC_MAP_tofrom;
          Data.IsMapTypeImplicit = true;
        }
d1707 7
a1713 7
  bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
                  Kind != OMPC_depend && Kind != OMPC_map) ||
                 (Kind == OMPC_reduction && !InvalidReductionId) ||
                 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
                  (!MapTypeModifierSpecified ||
                   Data.MapTypeModifier == OMPC_MAP_always)) ||
                 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
d1769 1
a1769 1
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'.
a1784 2
///    task_reduction-clause:
///       'task_reduction' '(' reduction-identifier ':' list ')'
@


1.1.1.12.4.1
log
@Sync with HEAD
@
text
@d10 1
a10 1
/// This file implements parsing of all OpenMP directives and clauses.
d83 1
a83 1
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
d88 38
a125 43
      {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
      {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
      {OMPD_declare, OMPD_simd, OMPD_declare_simd},
      {OMPD_declare, OMPD_target, OMPD_declare_target},
      {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
      {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
      {OMPD_distribute_parallel_for, OMPD_simd,
       OMPD_distribute_parallel_for_simd},
      {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
      {OMPD_end, OMPD_declare, OMPD_end_declare},
      {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
      {OMPD_target, OMPD_data, OMPD_target_data},
      {OMPD_target, OMPD_enter, OMPD_target_enter},
      {OMPD_target, OMPD_exit, OMPD_target_exit},
      {OMPD_target, OMPD_update, OMPD_target_update},
      {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
      {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
      {OMPD_for, OMPD_simd, OMPD_for_simd},
      {OMPD_parallel, OMPD_for, OMPD_parallel_for},
      {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
      {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
      {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
      {OMPD_target, OMPD_parallel, OMPD_target_parallel},
      {OMPD_target, OMPD_simd, OMPD_target_simd},
      {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
      {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
      {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
      {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
      {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
      {OMPD_teams_distribute_parallel, OMPD_for,
       OMPD_teams_distribute_parallel_for},
      {OMPD_teams_distribute_parallel_for, OMPD_simd,
       OMPD_teams_distribute_parallel_for_simd},
      {OMPD_target, OMPD_teams, OMPD_target_teams},
      {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
      {OMPD_target_teams_distribute, OMPD_parallel,
       OMPD_target_teams_distribute_parallel},
      {OMPD_target_teams_distribute, OMPD_simd,
       OMPD_target_teams_distribute_simd},
      {OMPD_target_teams_distribute_parallel, OMPD_for,
       OMPD_target_teams_distribute_parallel_for},
      {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
       OMPD_target_teams_distribute_parallel_for_simd}};
d127 1
a127 1
  Token Tok = P.getCurToken();
d135 2
a136 2
  for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
    if (DKind != F[I][0])
d147 1
a147 1
    if (SDKind == F[I][1]) {
d149 1
a149 1
      DKind = F[I][2];
d208 1
a208 1
/// Parse 'omp declare reduction' construct.
d253 1
a253 2
    TypeResult TR =
        ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
d255 1
a255 1
      QualType ReductionType =
d302 1
a302 1
  for (Decl *D : DRD.get()) {
a304 1
                                    Scope::CompoundStmtScope |
d324 1
a324 1
          Tok.getIdentifierInfo()->isStr("initializer")) {
d326 1
a326 1
      } else {
a339 1
                                        Scope::CompoundStmtScope |
d342 4
a345 13
        VarDecl *OmpPrivParm =
            Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
                                                                D);
        // Check if initializer is omp_priv <init_expr> or something else.
        if (Tok.is(tok::identifier) &&
            Tok.getIdentifierInfo()->isStr("omp_priv")) {
          ConsumeToken();
          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
        } else {
          InitializerResult = Actions.ActOnFinishFullExpr(
              ParseAssignmentExpression().get(), D->getLocation(),
              /*DiscardedValue=*/true);
        }
d347 1
a347 1
            D, InitializerResult.get(), OmpPrivParm);
a370 68
void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
  // Parse declarator '=' initializer.
  // If a '==' or '+=' is found, suggest a fixit to '='.
  if (isTokenEqualOrEqualTypo()) {
    ConsumeToken();

    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
      Actions.FinalizeDeclaration(OmpPrivParm);
      cutOffParsing();
      return;
    }

    ExprResult Init(ParseInitializer());

    if (Init.isInvalid()) {
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/false);
    }
  } else if (Tok.is(tok::l_paren)) {
    // Parse C++ direct initializer: '(' expression-list ')'
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();

    ExprVector Exprs;
    CommaLocsTy CommaLocs;

    if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
          Actions.CodeCompleteConstructor(
              getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
              OmpPrivParm->getLocation(), Exprs);
        })) {
      Actions.ActOnInitializerError(OmpPrivParm);
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
    } else {
      // Match the ')'.
      SourceLocation RLoc = Tok.getLocation();
      if (!T.consumeClose())
        RLoc = T.getCloseLocation();

      assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
             "Unexpected number of commas!");

      ExprResult Initializer =
          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
                                   /*DirectInit=*/true);
    }
  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
    // Parse C++0x braced-init-list.
    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

    ExprResult Init(ParseBraceInitializer());

    if (Init.isInvalid()) {
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/true);
    }
  } else {
    Actions.ActOnUninitializedDecl(OmpPrivParm);
  }
}

d408 2
a409 3
    FnScope = new Parser::ParseScope(
        &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
        HasFunScope);
d475 1
a475 1
        SmallVectorImpl<Expr *> *Vars = &Uniforms;
d485 1
a485 1
        if (CKind == OMPC_aligned) {
d487 1
a487 1
        } else if (CKind == OMPC_linear) {
d537 6
a542 5
  if (IsError)
    return Ptr;
  return Actions.ActOnOpenMPDeclareSimdDirective(
      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
      LinModifiers, Steps, SourceRange(Loc, EndLoc));
d545 1
a545 1
/// Parsing of declarative OpenMP directives.
d567 1
a567 1
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
d590 1
a590 1
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
d619 1
a619 1
    if (Tok.is(tok::annot_pragma_openmp)) {
d621 1
a621 1
    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
d643 1
a643 1
      Sema::NamedDeclSetType SameDirectiveDecls;
d659 2
a660 2
        auto &&Callback = [this, MT, &SameDirectiveDecls](
                              CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
d664 1
a664 2
        if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
                                     /*AllowScopeSpecifier=*/true))
d673 1
a673 5
      SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
                                   SameDirectiveDecls.end());
      if (Decls.empty())
        return DeclGroupPtrTy();
      return Actions.BuildDeclaratorGroup(Decls);
d682 1
a682 2
    llvm::SmallVector<Decl *, 4>  Decls;
    DKind = parseOpenMPDirectiveKind(*this);
d685 3
a687 15
      DeclGroupPtrTy Ptr;
      // Here we expect to see some function declaration.
      if (AS == AS_none) {
        assert(TagType == DeclSpec::TST_unspecified);
        MaybeParseCXX11Attributes(Attrs);
        ParsingDeclSpec PDS(*this);
        Ptr = ParseExternalDeclaration(Attrs, &PDS);
      } else {
        Ptr =
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
      }
      if (Ptr) {
        DeclGroupRef Ref = Ptr.get();
        Decls.append(Ref.begin(), Ref.end());
      }
d691 1
a691 1
        DKind = parseOpenMPDirectiveKind(*this);
d713 1
a713 1
    return Actions.BuildDeclaratorGroup(Decls);
d767 1
a767 1
        << 1 << getOpenMPDirectiveName(DKind);
d776 1
a776 1
/// Parsing of declarative or executable OpenMP directives.
d816 2
a817 2
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
d819 1
a819 1
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
d852 1
a852 2
    if (DeclGroupPtrTy Res =
            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
d863 1
a863 1
    } else {
a864 1
    }
d943 1
a943 1
      CancelRegion = parseOpenMPDirectiveKind(*this);
d996 1
d998 4
a1001 11
      // FIXME: We create a bogus CompoundStmt scope to hold the contents of
      // the captured region. Code elsewhere assumes that any FunctionScopeInfo
      // should have at least one compound statement scope within it.
      AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
    } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
               DKind == OMPD_target_exit_data) {
      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
      AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
                        Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
                                                  /*isStmtExpr=*/false));
d1017 1
a1017 1
        << 1 << getOpenMPDirectiveName(DKind);
d1048 1
d1060 1
a1060 1
                                  nullptr, Name)) {
d1092 1
a1092 1
/// Parsing of OpenMP clauses.
d1105 1
a1105 2
///       from-clause | is_device_ptr-clause | task_reduction-clause |
///       in_reduction-clause
a1110 1
  bool WrongDirective = false;
a1115 1
    WrongDirective = true;
d1159 1
a1159 1
      Clause = ParseOpenMPClause(CKind, WrongDirective);
d1161 1
a1161 1
      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
d1176 1
a1176 1
    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
d1193 1
a1193 1
    Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
d1216 1
a1216 1
    Clause = ParseOpenMPClause(CKind, WrongDirective);
a1223 1
  case OMPC_in_reduction:
d1235 1
a1235 1
    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
d1244 2
a1245 3
    if (!WrongDirective)
      Diag(Tok, diag::err_omp_unexpected_clause)
          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
d1268 1
a1268 3
  RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
d1270 1
d1274 1
a1274 1
/// Parsing of OpenMP clauses with single expressions like 'final',
d1305 1
a1305 2
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                               bool ParseOnly) {
a1314 2
  if (ParseOnly)
    return nullptr;
d1318 1
a1318 1
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
d1326 1
a1326 2
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
                                           bool ParseOnly) {
d1343 1
a1343 3
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
d1345 2
a1346 3
  if (ParseOnly)
    return nullptr;
  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
d1349 1
a1349 1
/// Parsing of OpenMP clauses like 'ordered'.
d1375 1
a1375 1
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
a1378 2
  if (ParseOnly)
    return nullptr;
d1383 1
a1383 1
/// Parsing of OpenMP clauses with single expressions and some additional
d1396 1
a1396 2
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
                                                      bool ParseOnly) {
d1415 1
a1415 1
    unsigned KindModifier = getOpenMPSimpleClauseType(
d1488 1
a1488 1
    Arg.push_back(parseOpenMPDirectiveKind(*this));
d1498 1
a1498 1
    } else {
a1499 1
    }
d1513 1
a1513 3
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
a1517 2
  if (ParseOnly)
    return nullptr;
d1519 2
a1520 1
      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
d1525 1
d1567 1
a1567 1
                              nullptr, nullptr, ReductionId);
d1589 1
a1589 2
  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
      Kind == OMPC_in_reduction) {
d1628 1
a1628 1
    if (Tok.is(tok::colon)) {
d1630 1
a1630 1
    } else {
d1679 1
a1679 1
          } else {
a1680 1
          }
d1704 1
a1704 1
          } else {
a1705 1
          }
d1737 7
a1743 8
  bool IsComma =
      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
       Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
      (Kind == OMPC_reduction && !InvalidReductionId) ||
      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
       (!MapTypeModifierSpecified ||
        Data.MapTypeModifier == OMPC_MAP_always)) ||
      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
d1751 1
a1751 1
    if (VarExpr.isUsable()) {
d1753 1
a1753 1
    } else {
d1789 7
a1795 7
  Data.RLoc = Tok.getLocation();
  if (!T.consumeClose())
    Data.RLoc = T.getCloseLocation();
  return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
          Vars.empty()) ||
         (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
         (MustHaveTail && !Data.TailExpr) || InvalidReductionId;
d1798 2
a1799 3
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
/// 'in_reduction'.
a1816 2
///    in_reduction-clause:
///       'in_reduction' '(' reduction-identifier ':' list ')'
d1840 1
a1840 2
                                            OpenMPClauseKind Kind,
                                            bool ParseOnly) {
a1848 2
  if (ParseOnly)
    return nullptr;
d1850 1
a1850 1
      Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc,
@


1.1.1.12.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.12.2.1
log
@Sync with HEAD
@
text
@d10 1
a10 1
/// This file implements parsing of all OpenMP directives and clauses.
d83 1
a83 1
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
d88 38
a125 43
      {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
      {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
      {OMPD_declare, OMPD_simd, OMPD_declare_simd},
      {OMPD_declare, OMPD_target, OMPD_declare_target},
      {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
      {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
      {OMPD_distribute_parallel_for, OMPD_simd,
       OMPD_distribute_parallel_for_simd},
      {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
      {OMPD_end, OMPD_declare, OMPD_end_declare},
      {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
      {OMPD_target, OMPD_data, OMPD_target_data},
      {OMPD_target, OMPD_enter, OMPD_target_enter},
      {OMPD_target, OMPD_exit, OMPD_target_exit},
      {OMPD_target, OMPD_update, OMPD_target_update},
      {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
      {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
      {OMPD_for, OMPD_simd, OMPD_for_simd},
      {OMPD_parallel, OMPD_for, OMPD_parallel_for},
      {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
      {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
      {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
      {OMPD_target, OMPD_parallel, OMPD_target_parallel},
      {OMPD_target, OMPD_simd, OMPD_target_simd},
      {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
      {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
      {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
      {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
      {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
      {OMPD_teams_distribute_parallel, OMPD_for,
       OMPD_teams_distribute_parallel_for},
      {OMPD_teams_distribute_parallel_for, OMPD_simd,
       OMPD_teams_distribute_parallel_for_simd},
      {OMPD_target, OMPD_teams, OMPD_target_teams},
      {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
      {OMPD_target_teams_distribute, OMPD_parallel,
       OMPD_target_teams_distribute_parallel},
      {OMPD_target_teams_distribute, OMPD_simd,
       OMPD_target_teams_distribute_simd},
      {OMPD_target_teams_distribute_parallel, OMPD_for,
       OMPD_target_teams_distribute_parallel_for},
      {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
       OMPD_target_teams_distribute_parallel_for_simd}};
d127 1
a127 1
  Token Tok = P.getCurToken();
d135 2
a136 2
  for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
    if (DKind != F[I][0])
d147 1
a147 1
    if (SDKind == F[I][1]) {
d149 1
a149 1
      DKind = F[I][2];
d208 1
a208 1
/// Parse 'omp declare reduction' construct.
d253 1
a253 2
    TypeResult TR =
        ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
d255 1
a255 1
      QualType ReductionType =
d302 1
a302 1
  for (Decl *D : DRD.get()) {
a304 1
                                    Scope::CompoundStmtScope |
d324 1
a324 1
          Tok.getIdentifierInfo()->isStr("initializer")) {
d326 1
a326 1
      } else {
a339 1
                                        Scope::CompoundStmtScope |
d342 4
a345 13
        VarDecl *OmpPrivParm =
            Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
                                                                D);
        // Check if initializer is omp_priv <init_expr> or something else.
        if (Tok.is(tok::identifier) &&
            Tok.getIdentifierInfo()->isStr("omp_priv")) {
          ConsumeToken();
          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
        } else {
          InitializerResult = Actions.ActOnFinishFullExpr(
              ParseAssignmentExpression().get(), D->getLocation(),
              /*DiscardedValue=*/true);
        }
d347 1
a347 1
            D, InitializerResult.get(), OmpPrivParm);
a370 68
void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
  // Parse declarator '=' initializer.
  // If a '==' or '+=' is found, suggest a fixit to '='.
  if (isTokenEqualOrEqualTypo()) {
    ConsumeToken();

    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
      Actions.FinalizeDeclaration(OmpPrivParm);
      cutOffParsing();
      return;
    }

    ExprResult Init(ParseInitializer());

    if (Init.isInvalid()) {
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/false);
    }
  } else if (Tok.is(tok::l_paren)) {
    // Parse C++ direct initializer: '(' expression-list ')'
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();

    ExprVector Exprs;
    CommaLocsTy CommaLocs;

    if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
          Actions.CodeCompleteConstructor(
              getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
              OmpPrivParm->getLocation(), Exprs);
        })) {
      Actions.ActOnInitializerError(OmpPrivParm);
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
    } else {
      // Match the ')'.
      SourceLocation RLoc = Tok.getLocation();
      if (!T.consumeClose())
        RLoc = T.getCloseLocation();

      assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
             "Unexpected number of commas!");

      ExprResult Initializer =
          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
                                   /*DirectInit=*/true);
    }
  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
    // Parse C++0x braced-init-list.
    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

    ExprResult Init(ParseBraceInitializer());

    if (Init.isInvalid()) {
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/true);
    }
  } else {
    Actions.ActOnUninitializedDecl(OmpPrivParm);
  }
}

d408 2
a409 3
    FnScope = new Parser::ParseScope(
        &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
        HasFunScope);
d475 1
a475 1
        SmallVectorImpl<Expr *> *Vars = &Uniforms;
d485 1
a485 1
        if (CKind == OMPC_aligned) {
d487 1
a487 1
        } else if (CKind == OMPC_linear) {
d537 6
a542 5
  if (IsError)
    return Ptr;
  return Actions.ActOnOpenMPDeclareSimdDirective(
      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
      LinModifiers, Steps, SourceRange(Loc, EndLoc));
d545 1
a545 1
/// Parsing of declarative OpenMP directives.
d567 1
a567 1
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
d590 1
a590 1
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
d619 1
a619 1
    if (Tok.is(tok::annot_pragma_openmp)) {
d621 1
a621 1
    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
d643 1
a643 1
      Sema::NamedDeclSetType SameDirectiveDecls;
d659 2
a660 2
        auto &&Callback = [this, MT, &SameDirectiveDecls](
                              CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
d664 1
a664 2
        if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
                                     /*AllowScopeSpecifier=*/true))
d673 1
a673 5
      SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
                                   SameDirectiveDecls.end());
      if (Decls.empty())
        return DeclGroupPtrTy();
      return Actions.BuildDeclaratorGroup(Decls);
d682 1
a682 2
    llvm::SmallVector<Decl *, 4>  Decls;
    DKind = parseOpenMPDirectiveKind(*this);
d685 3
a687 15
      DeclGroupPtrTy Ptr;
      // Here we expect to see some function declaration.
      if (AS == AS_none) {
        assert(TagType == DeclSpec::TST_unspecified);
        MaybeParseCXX11Attributes(Attrs);
        ParsingDeclSpec PDS(*this);
        Ptr = ParseExternalDeclaration(Attrs, &PDS);
      } else {
        Ptr =
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
      }
      if (Ptr) {
        DeclGroupRef Ref = Ptr.get();
        Decls.append(Ref.begin(), Ref.end());
      }
d691 1
a691 1
        DKind = parseOpenMPDirectiveKind(*this);
d713 1
a713 1
    return Actions.BuildDeclaratorGroup(Decls);
d767 1
a767 1
        << 1 << getOpenMPDirectiveName(DKind);
d776 1
a776 1
/// Parsing of declarative or executable OpenMP directives.
d816 2
a817 2
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
d819 1
a819 1
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
d852 1
a852 2
    if (DeclGroupPtrTy Res =
            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
d863 1
a863 1
    } else {
a864 1
    }
d943 1
a943 1
      CancelRegion = parseOpenMPDirectiveKind(*this);
d996 1
d998 4
a1001 11
      // FIXME: We create a bogus CompoundStmt scope to hold the contents of
      // the captured region. Code elsewhere assumes that any FunctionScopeInfo
      // should have at least one compound statement scope within it.
      AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
    } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
               DKind == OMPD_target_exit_data) {
      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
      AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
                        Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
                                                  /*isStmtExpr=*/false));
d1017 1
a1017 1
        << 1 << getOpenMPDirectiveName(DKind);
d1048 1
d1060 1
a1060 1
                                  nullptr, Name)) {
d1092 1
a1092 1
/// Parsing of OpenMP clauses.
d1105 1
a1105 2
///       from-clause | is_device_ptr-clause | task_reduction-clause |
///       in_reduction-clause
a1110 1
  bool WrongDirective = false;
a1115 1
    WrongDirective = true;
d1159 1
a1159 1
      Clause = ParseOpenMPClause(CKind, WrongDirective);
d1161 1
a1161 1
      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
d1176 1
a1176 1
    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
d1193 1
a1193 1
    Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
d1216 1
a1216 1
    Clause = ParseOpenMPClause(CKind, WrongDirective);
a1223 1
  case OMPC_in_reduction:
d1235 1
a1235 1
    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
d1244 2
a1245 3
    if (!WrongDirective)
      Diag(Tok, diag::err_omp_unexpected_clause)
          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
d1268 1
a1268 3
  RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
d1270 1
d1274 1
a1274 1
/// Parsing of OpenMP clauses with single expressions like 'final',
d1305 1
a1305 2
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                               bool ParseOnly) {
a1314 2
  if (ParseOnly)
    return nullptr;
d1318 1
a1318 1
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
d1326 1
a1326 2
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
                                           bool ParseOnly) {
d1343 1
a1343 3
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
d1345 2
a1346 3
  if (ParseOnly)
    return nullptr;
  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
d1349 1
a1349 1
/// Parsing of OpenMP clauses like 'ordered'.
d1375 1
a1375 1
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
a1378 2
  if (ParseOnly)
    return nullptr;
d1383 1
a1383 1
/// Parsing of OpenMP clauses with single expressions and some additional
d1396 1
a1396 2
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
                                                      bool ParseOnly) {
d1415 1
a1415 1
    unsigned KindModifier = getOpenMPSimpleClauseType(
d1488 1
a1488 1
    Arg.push_back(parseOpenMPDirectiveKind(*this));
d1498 1
a1498 1
    } else {
a1499 1
    }
d1513 1
a1513 3
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
a1517 2
  if (ParseOnly)
    return nullptr;
d1519 2
a1520 1
      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
d1525 1
d1567 1
a1567 1
                              nullptr, nullptr, ReductionId);
d1589 1
a1589 2
  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
      Kind == OMPC_in_reduction) {
d1628 1
a1628 1
    if (Tok.is(tok::colon)) {
d1630 1
a1630 1
    } else {
d1679 1
a1679 1
          } else {
a1680 1
          }
d1704 1
a1704 1
          } else {
a1705 1
          }
d1737 7
a1743 8
  bool IsComma =
      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
       Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
      (Kind == OMPC_reduction && !InvalidReductionId) ||
      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
       (!MapTypeModifierSpecified ||
        Data.MapTypeModifier == OMPC_MAP_always)) ||
      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
d1751 1
a1751 1
    if (VarExpr.isUsable()) {
d1753 1
a1753 1
    } else {
d1789 7
a1795 7
  Data.RLoc = Tok.getLocation();
  if (!T.consumeClose())
    Data.RLoc = T.getCloseLocation();
  return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
          Vars.empty()) ||
         (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
         (MustHaveTail && !Data.TailExpr) || InvalidReductionId;
d1798 2
a1799 3
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
/// 'in_reduction'.
a1816 2
///    in_reduction-clause:
///       'in_reduction' '(' reduction-identifier ':' list ')'
d1840 1
a1840 2
                                            OpenMPClauseKind Kind,
                                            bool ParseOnly) {
a1848 2
  if (ParseOnly)
    return nullptr;
d1850 1
a1850 1
      Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc,
@


1.1.1.13
log
@Import clang r337282 from trunk
@
text
@d10 1
a10 1
/// This file implements parsing of all OpenMP directives and clauses.
d83 1
a83 1
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
d88 38
a125 43
      {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
      {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
      {OMPD_declare, OMPD_simd, OMPD_declare_simd},
      {OMPD_declare, OMPD_target, OMPD_declare_target},
      {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
      {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
      {OMPD_distribute_parallel_for, OMPD_simd,
       OMPD_distribute_parallel_for_simd},
      {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
      {OMPD_end, OMPD_declare, OMPD_end_declare},
      {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
      {OMPD_target, OMPD_data, OMPD_target_data},
      {OMPD_target, OMPD_enter, OMPD_target_enter},
      {OMPD_target, OMPD_exit, OMPD_target_exit},
      {OMPD_target, OMPD_update, OMPD_target_update},
      {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
      {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
      {OMPD_for, OMPD_simd, OMPD_for_simd},
      {OMPD_parallel, OMPD_for, OMPD_parallel_for},
      {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
      {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
      {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
      {OMPD_target, OMPD_parallel, OMPD_target_parallel},
      {OMPD_target, OMPD_simd, OMPD_target_simd},
      {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
      {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
      {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
      {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
      {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
      {OMPD_teams_distribute_parallel, OMPD_for,
       OMPD_teams_distribute_parallel_for},
      {OMPD_teams_distribute_parallel_for, OMPD_simd,
       OMPD_teams_distribute_parallel_for_simd},
      {OMPD_target, OMPD_teams, OMPD_target_teams},
      {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
      {OMPD_target_teams_distribute, OMPD_parallel,
       OMPD_target_teams_distribute_parallel},
      {OMPD_target_teams_distribute, OMPD_simd,
       OMPD_target_teams_distribute_simd},
      {OMPD_target_teams_distribute_parallel, OMPD_for,
       OMPD_target_teams_distribute_parallel_for},
      {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
       OMPD_target_teams_distribute_parallel_for_simd}};
d127 1
a127 1
  Token Tok = P.getCurToken();
d135 2
a136 2
  for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
    if (DKind != F[I][0])
d147 1
a147 1
    if (SDKind == F[I][1]) {
d149 1
a149 1
      DKind = F[I][2];
d208 1
a208 1
/// Parse 'omp declare reduction' construct.
d253 1
a253 2
    TypeResult TR =
        ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
d255 1
a255 1
      QualType ReductionType =
d302 1
a302 1
  for (Decl *D : DRD.get()) {
a304 1
                                    Scope::CompoundStmtScope |
d324 1
a324 1
          Tok.getIdentifierInfo()->isStr("initializer")) {
d326 1
a326 1
      } else {
a339 1
                                        Scope::CompoundStmtScope |
d342 4
a345 13
        VarDecl *OmpPrivParm =
            Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
                                                                D);
        // Check if initializer is omp_priv <init_expr> or something else.
        if (Tok.is(tok::identifier) &&
            Tok.getIdentifierInfo()->isStr("omp_priv")) {
          ConsumeToken();
          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
        } else {
          InitializerResult = Actions.ActOnFinishFullExpr(
              ParseAssignmentExpression().get(), D->getLocation(),
              /*DiscardedValue=*/true);
        }
d347 1
a347 1
            D, InitializerResult.get(), OmpPrivParm);
a370 68
void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
  // Parse declarator '=' initializer.
  // If a '==' or '+=' is found, suggest a fixit to '='.
  if (isTokenEqualOrEqualTypo()) {
    ConsumeToken();

    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
      Actions.FinalizeDeclaration(OmpPrivParm);
      cutOffParsing();
      return;
    }

    ExprResult Init(ParseInitializer());

    if (Init.isInvalid()) {
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/false);
    }
  } else if (Tok.is(tok::l_paren)) {
    // Parse C++ direct initializer: '(' expression-list ')'
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();

    ExprVector Exprs;
    CommaLocsTy CommaLocs;

    if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
          Actions.CodeCompleteConstructor(
              getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
              OmpPrivParm->getLocation(), Exprs);
        })) {
      Actions.ActOnInitializerError(OmpPrivParm);
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
    } else {
      // Match the ')'.
      SourceLocation RLoc = Tok.getLocation();
      if (!T.consumeClose())
        RLoc = T.getCloseLocation();

      assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
             "Unexpected number of commas!");

      ExprResult Initializer =
          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
                                   /*DirectInit=*/true);
    }
  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
    // Parse C++0x braced-init-list.
    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

    ExprResult Init(ParseBraceInitializer());

    if (Init.isInvalid()) {
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/true);
    }
  } else {
    Actions.ActOnUninitializedDecl(OmpPrivParm);
  }
}

d408 2
a409 3
    FnScope = new Parser::ParseScope(
        &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
        HasFunScope);
d475 1
a475 1
        SmallVectorImpl<Expr *> *Vars = &Uniforms;
d485 1
a485 1
        if (CKind == OMPC_aligned) {
d487 1
a487 1
        } else if (CKind == OMPC_linear) {
d537 6
a542 5
  if (IsError)
    return Ptr;
  return Actions.ActOnOpenMPDeclareSimdDirective(
      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
      LinModifiers, Steps, SourceRange(Loc, EndLoc));
d545 1
a545 1
/// Parsing of declarative OpenMP directives.
d567 1
a567 1
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
d590 1
a590 1
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
d619 1
a619 1
    if (Tok.is(tok::annot_pragma_openmp)) {
d621 1
a621 1
    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
d643 1
a643 1
      Sema::NamedDeclSetType SameDirectiveDecls;
d659 2
a660 2
        auto &&Callback = [this, MT, &SameDirectiveDecls](
                              CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
d664 1
a664 2
        if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
                                     /*AllowScopeSpecifier=*/true))
d673 1
a673 5
      SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
                                   SameDirectiveDecls.end());
      if (Decls.empty())
        return DeclGroupPtrTy();
      return Actions.BuildDeclaratorGroup(Decls);
d682 1
a682 2
    llvm::SmallVector<Decl *, 4>  Decls;
    DKind = parseOpenMPDirectiveKind(*this);
d685 3
a687 15
      DeclGroupPtrTy Ptr;
      // Here we expect to see some function declaration.
      if (AS == AS_none) {
        assert(TagType == DeclSpec::TST_unspecified);
        MaybeParseCXX11Attributes(Attrs);
        ParsingDeclSpec PDS(*this);
        Ptr = ParseExternalDeclaration(Attrs, &PDS);
      } else {
        Ptr =
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
      }
      if (Ptr) {
        DeclGroupRef Ref = Ptr.get();
        Decls.append(Ref.begin(), Ref.end());
      }
d691 1
a691 1
        DKind = parseOpenMPDirectiveKind(*this);
d713 1
a713 1
    return Actions.BuildDeclaratorGroup(Decls);
d767 1
a767 1
        << 1 << getOpenMPDirectiveName(DKind);
d776 1
a776 1
/// Parsing of declarative or executable OpenMP directives.
d816 2
a817 2
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
d819 1
a819 1
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
d852 1
a852 2
    if (DeclGroupPtrTy Res =
            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
d863 1
a863 1
    } else {
a864 1
    }
d943 1
a943 1
      CancelRegion = parseOpenMPDirectiveKind(*this);
d996 1
d998 4
a1001 11
      // FIXME: We create a bogus CompoundStmt scope to hold the contents of
      // the captured region. Code elsewhere assumes that any FunctionScopeInfo
      // should have at least one compound statement scope within it.
      AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
    } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
               DKind == OMPD_target_exit_data) {
      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
      AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
                        Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
                                                  /*isStmtExpr=*/false));
d1017 1
a1017 1
        << 1 << getOpenMPDirectiveName(DKind);
d1048 1
d1060 1
a1060 1
                                  nullptr, Name)) {
d1092 1
a1092 1
/// Parsing of OpenMP clauses.
d1105 1
a1105 2
///       from-clause | is_device_ptr-clause | task_reduction-clause |
///       in_reduction-clause
a1110 1
  bool WrongDirective = false;
a1115 1
    WrongDirective = true;
d1159 1
a1159 1
      Clause = ParseOpenMPClause(CKind, WrongDirective);
d1161 1
a1161 1
      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
d1176 1
a1176 1
    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
d1193 1
a1193 1
    Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
d1216 1
a1216 1
    Clause = ParseOpenMPClause(CKind, WrongDirective);
a1223 1
  case OMPC_in_reduction:
d1235 1
a1235 1
    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
d1244 2
a1245 3
    if (!WrongDirective)
      Diag(Tok, diag::err_omp_unexpected_clause)
          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
d1268 1
a1268 3
  RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
d1270 1
d1274 1
a1274 1
/// Parsing of OpenMP clauses with single expressions like 'final',
d1305 1
a1305 2
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                               bool ParseOnly) {
a1314 2
  if (ParseOnly)
    return nullptr;
d1318 1
a1318 1
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
d1326 1
a1326 2
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
                                           bool ParseOnly) {
d1343 1
a1343 3
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
d1345 2
a1346 3
  if (ParseOnly)
    return nullptr;
  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
d1349 1
a1349 1
/// Parsing of OpenMP clauses like 'ordered'.
d1375 1
a1375 1
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
a1378 2
  if (ParseOnly)
    return nullptr;
d1383 1
a1383 1
/// Parsing of OpenMP clauses with single expressions and some additional
d1396 1
a1396 2
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
                                                      bool ParseOnly) {
d1415 1
a1415 1
    unsigned KindModifier = getOpenMPSimpleClauseType(
d1488 1
a1488 1
    Arg.push_back(parseOpenMPDirectiveKind(*this));
d1498 1
a1498 1
    } else {
a1499 1
    }
d1513 1
a1513 3
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();
a1517 2
  if (ParseOnly)
    return nullptr;
d1519 2
a1520 1
      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
d1525 1
d1567 1
a1567 1
                              nullptr, nullptr, ReductionId);
d1589 1
a1589 2
  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
      Kind == OMPC_in_reduction) {
d1628 1
a1628 1
    if (Tok.is(tok::colon)) {
d1630 1
a1630 1
    } else {
d1679 1
a1679 1
          } else {
a1680 1
          }
d1704 1
a1704 1
          } else {
a1705 1
          }
d1737 7
a1743 8
  bool IsComma =
      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
       Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
      (Kind == OMPC_reduction && !InvalidReductionId) ||
      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
       (!MapTypeModifierSpecified ||
        Data.MapTypeModifier == OMPC_MAP_always)) ||
      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
d1751 1
a1751 1
    if (VarExpr.isUsable()) {
d1753 1
a1753 1
    } else {
d1789 7
a1795 7
  Data.RLoc = Tok.getLocation();
  if (!T.consumeClose())
    Data.RLoc = T.getCloseLocation();
  return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
          Vars.empty()) ||
         (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
         (MustHaveTail && !Data.TailExpr) || InvalidReductionId;
d1798 2
a1799 3
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
/// 'in_reduction'.
a1816 2
///    in_reduction-clause:
///       'in_reduction' '(' reduction-identifier ':' list ')'
d1840 1
a1840 2
                                            OpenMPClauseKind Kind,
                                            bool ParseOnly) {
a1848 2
  if (ParseOnly)
    return nullptr;
d1850 1
a1850 1
      Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc,
@


1.1.1.14
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.7.4.1
log
@file ParseOpenMP.cpp was added on branch tls-maxphys on 2014-08-19 23:47:29 +0000
@
text
@d1 746
@


1.1.1.7.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 746
//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// \brief This file implements parsing of all OpenMP directives and clauses.
///
//===----------------------------------------------------------------------===//

#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//

static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
  auto Tok = P.getCurToken();
  auto DKind =
      Tok.isAnnotation()
          ? OMPD_unknown
          : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
  if (DKind == OMPD_parallel) {
    Tok = P.getPreprocessor().LookAhead(0);
    auto SDKind =
        Tok.isAnnotation()
            ? OMPD_unknown
            : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
    if (SDKind == OMPD_for) {
      P.ConsumeToken();
      DKind = OMPD_parallel_for;
    } else if (SDKind == OMPD_sections) {
      P.ConsumeToken();
      DKind = OMPD_parallel_sections;
    }
  }
  return DKind;
}

/// \brief Parsing of declarative OpenMP directives.
///
///       threadprivate-directive:
///         annot_pragma_openmp 'threadprivate' simple-variable-list
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
  ParenBraceBracketBalancer BalancerRAIIObj(*this);

  SourceLocation Loc = ConsumeToken();
  SmallVector<Expr *, 5> Identifiers;
  auto DKind = ParseOpenMPDirectiveKind(*this);

  switch (DKind) {
  case OMPD_threadprivate:
    ConsumeToken();
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_threadprivate);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeToken();
      return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
    }
    break;
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    break;
  case OMPD_parallel:
  case OMPD_simd:
  case OMPD_task:
  case OMPD_taskyield:
  case OMPD_barrier:
  case OMPD_taskwait:
  case OMPD_flush:
  case OMPD_for:
  case OMPD_sections:
  case OMPD_section:
  case OMPD_single:
  case OMPD_master:
  case OMPD_ordered:
  case OMPD_critical:
  case OMPD_parallel_for:
  case OMPD_parallel_sections:
  case OMPD_atomic:
    Diag(Tok, diag::err_omp_unexpected_directive)
        << getOpenMPDirectiveName(DKind);
    break;
  }
  SkipUntil(tok::annot_pragma_openmp_end);
  return DeclGroupPtrTy();
}

/// \brief Parsing of declarative or executable OpenMP directives.
///
///       threadprivate-directive:
///         annot_pragma_openmp 'threadprivate' simple-variable-list
///         annot_pragma_openmp_end
///
///       executable-directive:
///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' {clause}
///         annot_pragma_openmp_end
///
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
  SmallVector<Expr *, 5> Identifiers;
  SmallVector<OMPClause *, 5> Clauses;
  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
  FirstClauses(OMPC_unknown + 1);
  unsigned ScopeFlags =
      Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
  SourceLocation Loc = ConsumeToken(), EndLoc;
  auto DKind = ParseOpenMPDirectiveKind(*this);
  // Name of critical directive.
  DeclarationNameInfo DirName;
  StmtResult Directive = StmtError();
  bool HasAssociatedStatement = true;
  bool FlushHasClause = false;

  switch (DKind) {
  case OMPD_threadprivate:
    ConsumeToken();
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
            << getOpenMPDirectiveName(OMPD_threadprivate);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      DeclGroupPtrTy Res =
          Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    }
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  case OMPD_flush:
    if (PP.LookAhead(0).is(tok::l_paren)) {
      FlushHasClause = true;
      // Push copy of the current token back to stream to properly parse
      // pseudo-clause OMPFlushClause.
      PP.EnterToken(Tok);
    }
  case OMPD_taskyield:
  case OMPD_barrier:
  case OMPD_taskwait:
    if (!StandAloneAllowed) {
      Diag(Tok, diag::err_omp_immediate_directive)
          << getOpenMPDirectiveName(DKind);
    }
    HasAssociatedStatement = false;
    // Fall through for further analysis.
  case OMPD_parallel:
  case OMPD_simd:
  case OMPD_for:
  case OMPD_sections:
  case OMPD_single:
  case OMPD_section:
  case OMPD_master:
  case OMPD_critical:
  case OMPD_parallel_for:
  case OMPD_parallel_sections:
  case OMPD_task:
  case OMPD_ordered:
  case OMPD_atomic: {
    ConsumeToken();
    // Parse directive name of the 'critical' directive if any.
    if (DKind == OMPD_critical) {
      BalancedDelimiterTracker T(*this, tok::l_paren,
                                 tok::annot_pragma_openmp_end);
      if (!T.consumeOpen()) {
        if (Tok.isAnyIdentifier()) {
          DirName =
              DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
          ConsumeAnyToken();
        } else {
          Diag(Tok, diag::err_omp_expected_identifier_for_critical);
        }
        T.consumeClose();
      }
    }

    if (isOpenMPLoopDirective(DKind))
      ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
    if (isOpenMPSimdDirective(DKind))
      ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
    ParseScope OMPDirectiveScope(this, ScopeFlags);
    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);

    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      OpenMPClauseKind CKind =
          Tok.isAnnotation()
              ? OMPC_unknown
              : FlushHasClause ? OMPC_flush
                               : getOpenMPClauseKind(PP.getSpelling(Tok));
      FlushHasClause = false;
      OMPClause *Clause =
          ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
      FirstClauses[CKind].setInt(true);
      if (Clause) {
        FirstClauses[CKind].setPointer(Clause);
        Clauses.push_back(Clause);
      }

      // Skip ',' if any.
      if (Tok.is(tok::comma))
        ConsumeToken();
    }
    // End location of the directive.
    EndLoc = Tok.getLocation();
    // Consume final annot_pragma_openmp_end.
    ConsumeToken();

    StmtResult AssociatedStmt;
    bool CreateDirective = true;
    if (HasAssociatedStatement) {
      // The body is a block scope like in Lambdas and Blocks.
      Sema::CompoundScopeRAII CompoundScope(Actions);
      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
      Actions.ActOnStartOfCompoundStmt();
      // Parse statement
      AssociatedStmt = ParseStatement();
      Actions.ActOnFinishOfCompoundStmt();
      if (!AssociatedStmt.isUsable()) {
        Actions.ActOnCapturedRegionError();
        CreateDirective = false;
      } else {
        AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
        CreateDirective = AssociatedStmt.isUsable();
      }
    }
    if (CreateDirective)
      Directive = Actions.ActOnOpenMPExecutableDirective(
          DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);

    // Exit scope.
    Actions.EndOpenMPDSABlock(Directive.get());
    OMPDirectiveScope.Exit();
    break;
  }
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  }
  return Directive;
}

/// \brief Parses list of simple variables for '#pragma omp threadprivate'
/// directive.
///
///   simple-variable-list:
///         '(' id-expression {, id-expression} ')'
///
bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
                                      SmallVectorImpl<Expr *> &VarList,
                                      bool AllowScopeSpecifier) {
  VarList.clear();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPDirectiveName(Kind)))
    return true;
  bool IsCorrect = true;
  bool NoIdentIsFound = true;

  // Read tokens while ')' or annot_pragma_openmp_end is not found.
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    CXXScopeSpec SS;
    SourceLocation TemplateKWLoc;
    UnqualifiedId Name;
    // Read var name.
    Token PrevTok = Tok;
    NoIdentIsFound = false;

    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
                                  TemplateKWLoc, Name)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
               Tok.isNot(tok::annot_pragma_openmp_end)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
      Diag(PrevTok.getLocation(), diag::err_expected)
          << tok::identifier
          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
    } else {
      DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
      ExprResult Res =
          Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
      if (Res.isUsable())
        VarList.push_back(Res.get());
    }
    // Consume ','.
    if (Tok.is(tok::comma)) {
      ConsumeToken();
    }
  }

  if (NoIdentIsFound) {
    Diag(Tok, diag::err_expected) << tok::identifier;
    IsCorrect = false;
  }

  // Parse ')'.
  IsCorrect = !T.consumeClose() && IsCorrect;

  return !IsCorrect && VarList.empty();
}

/// \brief Parsing of OpenMP clauses.
///
///    clause:
///       if-clause | final-clause | num_threads-clause | safelen-clause |
///       default-clause | private-clause | firstprivate-clause | shared-clause
///       | linear-clause | aligned-clause | collapse-clause |
///       lastprivate-clause | reduction-clause | proc_bind-clause |
///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
///       mergeable-clause | flush-clause | read-clause | write-clause |
///       update-clause | capture-clause | seq_cst-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                     OpenMPClauseKind CKind, bool FirstClause) {
  OMPClause *Clause = nullptr;
  bool ErrorFound = false;
  // Check if clause is allowed for the given directive.
  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
                                               << getOpenMPDirectiveName(DKind);
    ErrorFound = true;
  }

  switch (CKind) {
  case OMPC_if:
  case OMPC_final:
  case OMPC_num_threads:
  case OMPC_safelen:
  case OMPC_collapse:
    // OpenMP [2.5, Restrictions]
    //  At most one if clause can appear on the directive.
    //  At most one num_threads clause can appear on the directive.
    // OpenMP [2.8.1, simd construct, Restrictions]
    //  Only one safelen  clause can appear on a simd directive.
    //  Only one collapse clause can appear on a simd directive.
    // OpenMP [2.11.1, task Construct, Restrictions]
    //  At most one if clause can appear on the directive.
    //  At most one final clause can appear on the directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
      ErrorFound = true;
    }

    Clause = ParseOpenMPSingleExprClause(CKind);
    break;
  case OMPC_default:
  case OMPC_proc_bind:
    // OpenMP [2.14.3.1, Restrictions]
    //  Only a single default clause may be specified on a parallel, task or
    //  teams directive.
    // OpenMP [2.5, parallel Construct, Restrictions]
    //  At most one proc_bind clause can appear on the directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
      ErrorFound = true;
    }

    Clause = ParseOpenMPSimpleClause(CKind);
    break;
  case OMPC_schedule:
    // OpenMP [2.7.1, Restrictions, p. 3]
    //  Only one schedule clause can appear on a loop directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
      ErrorFound = true;
    }

    Clause = ParseOpenMPSingleExprWithArgClause(CKind);
    break;
  case OMPC_ordered:
  case OMPC_nowait:
  case OMPC_untied:
  case OMPC_mergeable:
  case OMPC_read:
  case OMPC_write:
  case OMPC_update:
  case OMPC_capture:
  case OMPC_seq_cst:
    // OpenMP [2.7.1, Restrictions, p. 9]
    //  Only one ordered clause can appear on a loop directive.
    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
    //  Only one nowait clause can appear on a for directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
                                               << getOpenMPClauseName(CKind);
      ErrorFound = true;
    }

    Clause = ParseOpenMPClause(CKind);
    break;
  case OMPC_private:
  case OMPC_firstprivate:
  case OMPC_lastprivate:
  case OMPC_shared:
  case OMPC_reduction:
  case OMPC_linear:
  case OMPC_aligned:
  case OMPC_copyin:
  case OMPC_copyprivate:
  case OMPC_flush:
    Clause = ParseOpenMPVarListClause(CKind);
    break;
  case OMPC_unknown:
    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
        << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  case OMPC_threadprivate:
    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
                                               << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  }
  return ErrorFound ? nullptr : Clause;
}

/// \brief Parsing of OpenMP clauses with single expressions like 'if',
/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
/// 'thread_limit'.
///
///    if-clause:
///      'if' '(' expression ')'
///
///    final-clause:
///      'final' '(' expression ')'
///
///    num_threads-clause:
///      'num_threads' '(' expression ')'
///
///    safelen-clause:
///      'safelen' '(' expression ')'
///
///    collapse-clause:
///      'collapse' '(' expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = ConsumeToken();

  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));

  // Parse ')'.
  T.consumeClose();

  if (Val.isInvalid())
    return nullptr;

  return Actions.ActOnOpenMPSingleExprClause(
      Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
}

/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
///    default-clause:
///         'default' '(' 'none' | 'shared' ')
///
///    proc_bind-clause:
///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  unsigned Type = getOpenMPSimpleClauseType(
      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
  SourceLocation TypeLoc = Tok.getLocation();
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  // Parse ')'.
  T.consumeClose();

  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
                                         Tok.getLocation());
}

/// \brief Parsing of OpenMP clauses like 'ordered'.
///
///    ordered-clause:
///         'ordered'
///
///    nowait-clause:
///         'nowait'
///
///    untied-clause:
///         'untied'
///
///    mergeable-clause:
///         'mergeable'
///
///    read-clause:
///         'read'
///
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  ConsumeAnyToken();

  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
}


/// \brief Parsing of OpenMP clauses with single expressions and some additional
/// argument like 'schedule' or 'dist_schedule'.
///
///    schedule-clause:
///      'schedule' '(' kind [',' expression ] ')'
///
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = ConsumeToken();
  SourceLocation CommaLoc;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  ExprResult Val;
  unsigned Type = getOpenMPSimpleClauseType(
      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
  SourceLocation KLoc = Tok.getLocation();
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  if (Kind == OMPC_schedule &&
      (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
       Type == OMPC_SCHEDULE_guided) &&
      Tok.is(tok::comma)) {
    CommaLoc = ConsumeAnyToken();
    ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
    if (Val.isInvalid())
      return nullptr;
  }

  // Parse ')'.
  T.consumeClose();

  return Actions.ActOnOpenMPSingleExprWithArgClause(
      Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
      T.getCloseLocation());
}

static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
                             UnqualifiedId &ReductionId) {
  SourceLocation TemplateKWLoc;
  if (ReductionIdScopeSpec.isEmpty()) {
    auto OOK = OO_None;
    switch (P.getCurToken().getKind()) {
    case tok::plus:
      OOK = OO_Plus;
      break;
    case tok::minus:
      OOK = OO_Minus;
      break;
    case tok::star:
      OOK = OO_Star;
      break;
    case tok::amp:
      OOK = OO_Amp;
      break;
    case tok::pipe:
      OOK = OO_Pipe;
      break;
    case tok::caret:
      OOK = OO_Caret;
      break;
    case tok::ampamp:
      OOK = OO_AmpAmp;
      break;
    case tok::pipepipe:
      OOK = OO_PipePipe;
      break;
    default:
      break;
    }
    if (OOK != OO_None) {
      SourceLocation OpLoc = P.ConsumeToken();
      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
      return false;
    }
  }
  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
                              /*AllowDestructorName*/ false,
                              /*AllowConstructorName*/ false, ParsedType(),
                              TemplateKWLoc, ReductionId);
}

/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  SourceLocation ColonLoc = SourceLocation();
  // Optional scope specifier and unqualified id for reduction identifier.
  CXXScopeSpec ReductionIdScopeSpec;
  UnqualifiedId ReductionId;
  bool InvalidReductionId = false;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  // Handle reduction-identifier for reduction clause.
  if (Kind == OMPC_reduction) {
    ColonProtectionRAIIObject ColonRAII(*this);
    if (getLangOpts().CPlusPlus) {
      ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
    }
    InvalidReductionId =
        ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
    if (InvalidReductionId) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
    }
  }

  SmallVector<Expr *, 5> Vars;
  bool IsComma = !InvalidReductionId;
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
    // Parse variable
    ExprResult VarExpr = ParseAssignmentExpression();
    if (VarExpr.isUsable()) {
      Vars.push_back(VarExpr.get());
    } else {
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    // Skip ',' if any
    IsComma = Tok.is(tok::comma);
    if (IsComma)
      ConsumeToken();
    else if (Tok.isNot(tok::r_paren) &&
             Tok.isNot(tok::annot_pragma_openmp_end) &&
             (!MayHaveTail || Tok.isNot(tok::colon)))
      Diag(Tok, diag::err_omp_expected_punc)
          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
                                   : getOpenMPClauseName(Kind))
          << (Kind == OMPC_flush);
  }

  // Parse ':' linear-step (or ':' alignment).
  Expr *TailExpr = nullptr;
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
  if (MustHaveTail) {
    ColonLoc = Tok.getLocation();
    ConsumeToken();
    ExprResult Tail = ParseAssignmentExpression();
    if (Tail.isUsable())
      TailExpr = Tail.get();
    else
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
  }

  // Parse ')'.
  T.consumeClose();
  if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
    return nullptr;

  return Actions.ActOnOpenMPVarListClause(
      Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
      ReductionIdScopeSpec,
      ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
                            : DeclarationNameInfo());
}

@


1.1.1.5.4.1
log
@file ParseOpenMP.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:29 +0000
@
text
@d1 427
@


1.1.1.5.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 427
//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// \brief This file implements parsing of all OpenMP directives and clauses.
///
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//

/// \brief Parsing of declarative OpenMP directives.
///
///       threadprivate-directive:
///         annot_pragma_openmp 'threadprivate' simple-variable-list
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
  ParenBraceBracketBalancer BalancerRAIIObj(*this);

  SourceLocation Loc = ConsumeToken();
  SmallVector<Expr *, 5> Identifiers;
  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
                                  OMPD_unknown :
                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));

  switch (DKind) {
  case OMPD_threadprivate:
    ConsumeToken();
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
          << getOpenMPDirectiveName(OMPD_threadprivate);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeToken();
      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
                                                       Identifiers);
    }
    break;
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    break;
  case OMPD_parallel:
  case OMPD_simd:
  case OMPD_task:
  case NUM_OPENMP_DIRECTIVES:
    Diag(Tok, diag::err_omp_unexpected_directive)
      << getOpenMPDirectiveName(DKind);
    break;
  }
  SkipUntil(tok::annot_pragma_openmp_end);
  return DeclGroupPtrTy();
}

/// \brief Parsing of declarative or executable OpenMP directives.
///
///       threadprivate-directive:
///         annot_pragma_openmp 'threadprivate' simple-variable-list
///         annot_pragma_openmp_end
///
///       parallel-directive:
///         annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
///
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
  SmallVector<Expr *, 5> Identifiers;
  SmallVector<OMPClause *, 5> Clauses;
  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
                                               FirstClauses(NUM_OPENMP_CLAUSES);
  const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                              Scope::OpenMPDirectiveScope;
  SourceLocation Loc = ConsumeToken(), EndLoc;
  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
                                  OMPD_unknown :
                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));
  // Name of critical directive.
  DeclarationNameInfo DirName;
  StmtResult Directive = StmtError();

  switch (DKind) {
  case OMPD_threadprivate:
    ConsumeToken();
    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
      // The last seen token is annot_pragma_openmp_end - need to check for
      // extra tokens.
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
          << getOpenMPDirectiveName(OMPD_threadprivate);
        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
      }
      DeclGroupPtrTy Res =
        Actions.ActOnOpenMPThreadprivateDirective(Loc,
                                                  Identifiers);
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    }
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  case OMPD_parallel:
  case OMPD_simd: {
    ConsumeToken();

    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());

    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      OpenMPClauseKind CKind = Tok.isAnnotation() ?
                                  OMPC_unknown :
                                  getOpenMPClauseKind(PP.getSpelling(Tok));
      OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
                                            !FirstClauses[CKind].getInt());
      FirstClauses[CKind].setInt(true);
      if (Clause) {
        FirstClauses[CKind].setPointer(Clause);
        Clauses.push_back(Clause);
      }

      // Skip ',' if any.
      if (Tok.is(tok::comma))
        ConsumeToken();
    }
    // End location of the directive.
    EndLoc = Tok.getLocation();
    // Consume final annot_pragma_openmp_end.
    ConsumeToken();

    StmtResult AssociatedStmt;
    bool CreateDirective = true;
    ParseScope OMPDirectiveScope(this, ScopeFlags);
    {
      // The body is a block scope like in Lambdas and Blocks.
      Sema::CompoundScopeRAII CompoundScope(Actions);
      Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1);
      Actions.ActOnStartOfCompoundStmt();
      // Parse statement
      AssociatedStmt = ParseStatement();
      Actions.ActOnFinishOfCompoundStmt();
      if (!AssociatedStmt.isUsable()) {
        Actions.ActOnCapturedRegionError();
        CreateDirective = false;
      } else {
        AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
        CreateDirective = AssociatedStmt.isUsable();
      }
    }
    if (CreateDirective)
      Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
                                                         AssociatedStmt.take(),
                                                         Loc, EndLoc);

    // Exit scope.
    Actions.EndOpenMPDSABlock(Directive.get());
    OMPDirectiveScope.Exit();
    }
    break;
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  case OMPD_task:
  case NUM_OPENMP_DIRECTIVES:
    Diag(Tok, diag::err_omp_unexpected_directive)
      << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  }
  return Directive;
}

/// \brief Parses list of simple variables for '#pragma omp threadprivate'
/// directive.
///
///   simple-variable-list:
///         '(' id-expression {, id-expression} ')'
///
bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
                                      SmallVectorImpl<Expr *> &VarList,
                                      bool AllowScopeSpecifier) {
  VarList.clear();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPDirectiveName(Kind)))
    return true;
  bool IsCorrect = true;
  bool NoIdentIsFound = true;

  // Read tokens while ')' or annot_pragma_openmp_end is not found.
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    CXXScopeSpec SS;
    SourceLocation TemplateKWLoc;
    UnqualifiedId Name;
    // Read var name.
    Token PrevTok = Tok;
    NoIdentIsFound = false;

    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
                                  TemplateKWLoc, Name)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
               Tok.isNot(tok::annot_pragma_openmp_end)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
      Diag(PrevTok.getLocation(), diag::err_expected)
          << tok::identifier
          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
    } else {
      DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
      ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
                                                       NameInfo);
      if (Res.isUsable())
        VarList.push_back(Res.take());
    }
    // Consume ','.
    if (Tok.is(tok::comma)) {
      ConsumeToken();
    }
  }

  if (NoIdentIsFound) {
    Diag(Tok, diag::err_expected) << tok::identifier;
    IsCorrect = false;
  }

  // Parse ')'.
  IsCorrect = !T.consumeClose() && IsCorrect;

  return !IsCorrect && VarList.empty();
}

/// \brief Parsing of OpenMP clauses.
///
///    clause:
///       default-clause|private-clause|firstprivate-clause|shared-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                     OpenMPClauseKind CKind, bool FirstClause) {
  OMPClause *Clause = 0;
  bool ErrorFound = false;
  // Check if clause is allowed for the given directive.
  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
    Diag(Tok, diag::err_omp_unexpected_clause)
      << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
    ErrorFound = true;
  }

  switch (CKind) {
  case OMPC_if:
    // OpenMP [2.5, Restrictions]
    //  At most one if clause can appear on the directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
    }

    Clause = ParseOpenMPSingleExprClause(CKind);
    break;
  case OMPC_default:
    // OpenMP [2.14.3.1, Restrictions]
    //  Only a single default clause may be specified on a parallel, task or
    //  teams directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
    }

    Clause = ParseOpenMPSimpleClause(CKind);
    break;
  case OMPC_private:
  case OMPC_firstprivate:
  case OMPC_shared:
    Clause = ParseOpenMPVarListClause(CKind);
    break;
  case OMPC_unknown:
    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
      << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  case OMPC_threadprivate:
  case NUM_OPENMP_CLAUSES:
    Diag(Tok, diag::err_omp_unexpected_clause)
      << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  }
  return ErrorFound ? 0 : Clause;
}

/// \brief Parsing of OpenMP clauses with single expressions like 'if',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
/// 'thread_limit'.
///
///    if-clause:
///      'if' '(' expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = ConsumeToken();

  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return 0;

  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));

  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  // Parse ')'.
  T.consumeClose();

  if (Val.isInvalid())
    return 0;

  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.take(), Loc,
                                             T.getOpenLocation(),
                                             T.getCloseLocation());
}

/// \brief Parsing of simple OpenMP clauses like 'default'.
///
///    default-clause:
///         'default' '(' 'none' | 'shared' ')
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return 0;

  unsigned Type = Tok.isAnnotation() ?
                     unsigned(OMPC_DEFAULT_unknown) :
                     getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
  SourceLocation TypeLoc = Tok.getLocation();
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();

  // Parse ')'.
  T.consumeClose();

  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
                                         Tok.getLocation());
}

/// \brief Parsing of OpenMP clause 'private', 'firstprivate',
/// 'shared', 'copyin', or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return 0;

  SmallVector<Expr *, 5> Vars;
  bool IsComma = true;
  while (IsComma || (Tok.isNot(tok::r_paren) &&
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
    // Parse variable
    ExprResult VarExpr = ParseAssignmentExpression();
    if (VarExpr.isUsable()) {
      Vars.push_back(VarExpr.take());
    } else {
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    // Skip ',' if any
    IsComma = Tok.is(tok::comma);
    if (IsComma) {
      ConsumeToken();
    } else if (Tok.isNot(tok::r_paren) &&
               Tok.isNot(tok::annot_pragma_openmp_end)) {
      Diag(Tok, diag::err_omp_expected_punc)
        << getOpenMPClauseName(Kind);
    }
  }

  // Parse ')'.
  T.consumeClose();
  if (Vars.empty())
    return 0;

  return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
                                          Tok.getLocation());
}

@


