diff options
Diffstat (limited to 'lib/Parse/ParseOpenMP.cpp')
-rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp new file mode 100644 index 0000000..507a6b1 --- /dev/null +++ b/lib/Parse/ParseOpenMP.cpp @@ -0,0 +1,118 @@ +//===--- 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/Parse/Parser.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "RAIIObjectsForParser.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// OpenMP declarative directives. +//===----------------------------------------------------------------------===// + +/// \brief Parses OpenMP declarative directive +/// threadprivate-directive +/// annot_pragma_openmp threadprivate simple-variable-list +/// +Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { + assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + + SourceLocation Loc = ConsumeToken(); + SmallVector<DeclarationNameInfo, 5> Identifiers; + OpenMPDirectiveKind Kind = Tok.isAnnotation() ? + OMPD_unknown : + getOpenMPDirectiveKind(PP.getSpelling(Tok)); + switch(Kind) { + case OMPD_threadprivate: + ConsumeToken(); + if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) { + // 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, false, true); + } + ConsumeToken(); + return Actions.ActOnOpenMPThreadprivateDirective(Loc, + getCurScope(), + Identifiers); + } + break; + case OMPD_unknown: + Diag(Tok, diag::err_omp_unknown_directive); + break; + default: + Diag(Tok, diag::err_omp_unexpected_directive) + << getOpenMPDirectiveName(Kind); + break; + } + SkipUntil(tok::annot_pragma_openmp_end, false); + return DeclGroupPtrTy(); +} + +/// \brief Parses list of simple variables for '#pragma omp threadprivate' +/// directive +/// simple-variable-list: +/// ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end +/// +bool Parser::ParseOpenMPSimpleVarList( + OpenMPDirectiveKind Kind, + SmallVectorImpl<DeclarationNameInfo> &IdList) { + // Parse '('. + bool IsCorrect = true; + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPDirectiveName(Kind))) { + SkipUntil(tok::annot_pragma_openmp_end, false, true); + return false; + } + + // Read tokens while ')' or annot_pragma_openmp_end is not found. + do { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + // Read var name. + Token PrevTok = Tok; + + if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), + TemplateKWLoc, Name)) { + IsCorrect = false; + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + false, true); + } + 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, + false, true); + Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus + << SourceRange(PrevTok.getLocation(), PrevTokLocation); + } else { + IdList.push_back(Actions.GetNameFromUnqualifiedId(Name)); + } + // Consume ','. + if (Tok.is(tok::comma)) { + ConsumeToken(); + } + } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); + + if (IsCorrect || Tok.is(tok::r_paren)) { + IsCorrect = !T.consumeClose() && IsCorrect; + } + + return !IsCorrect && IdList.empty(); +} |