| //===--- 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/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!"); |
| |
| 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, false, true); |
| } |
| // 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; |
| default: |
| Diag(Tok, diag::err_omp_unexpected_directive) |
| << getOpenMPDirectiveName(DKind); |
| break; |
| } |
| SkipUntil(tok::annot_pragma_openmp_end, false); |
| return DeclGroupPtrTy(); |
| } |
| |
| /// \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); |
| bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after, |
| getOpenMPDirectiveName(Kind)); |
| bool IsCorrect = LParen; |
| 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, |
| false, true); |
| } else 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_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 = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose()) |
| && IsCorrect; |
| |
| return !IsCorrect && VarList.empty(); |
| } |