//===--- 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 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 &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(); }