Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 1 | //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | /// \file |
| 10 | /// \brief This file implements parsing of all OpenMP directives and clauses. |
| 11 | /// |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "clang/AST/ASTConsumer.h" |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 15 | #include "clang/Parse/ParseDiagnostic.h" |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 16 | #include "clang/Parse/Parser.h" |
| 17 | #include "clang/Sema/Scope.h" |
| 18 | #include "llvm/ADT/PointerIntPair.h" |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 19 | #include "RAIIObjectsForParser.h" |
| 20 | using namespace clang; |
| 21 | |
| 22 | //===----------------------------------------------------------------------===// |
| 23 | // OpenMP declarative directives. |
| 24 | //===----------------------------------------------------------------------===// |
| 25 | |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 26 | /// \brief Parsing of declarative OpenMP directives. |
| 27 | /// |
| 28 | /// threadprivate-directive: |
| 29 | /// annot_pragma_openmp 'threadprivate' simple-variable-list |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 30 | /// |
| 31 | Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { |
| 32 | assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); |
| 33 | |
| 34 | SourceLocation Loc = ConsumeToken(); |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 35 | SmallVector<Expr *, 5> Identifiers; |
| 36 | OpenMPDirectiveKind DKind = Tok.isAnnotation() ? |
| 37 | OMPD_unknown : |
| 38 | getOpenMPDirectiveKind(PP.getSpelling(Tok)); |
| 39 | |
| 40 | switch (DKind) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 41 | case OMPD_threadprivate: |
| 42 | ConsumeToken(); |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 43 | if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 44 | // The last seen token is annot_pragma_openmp_end - need to check for |
| 45 | // extra tokens. |
| 46 | if (Tok.isNot(tok::annot_pragma_openmp_end)) { |
| 47 | Diag(Tok, diag::warn_omp_extra_tokens_at_eol) |
| 48 | << getOpenMPDirectiveName(OMPD_threadprivate); |
| 49 | SkipUntil(tok::annot_pragma_openmp_end, false, true); |
| 50 | } |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 51 | // Skip the last annot_pragma_openmp_end. |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 52 | ConsumeToken(); |
| 53 | return Actions.ActOnOpenMPThreadprivateDirective(Loc, |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 54 | Identifiers); |
| 55 | } |
| 56 | break; |
| 57 | case OMPD_unknown: |
| 58 | Diag(Tok, diag::err_omp_unknown_directive); |
| 59 | break; |
| 60 | default: |
| 61 | Diag(Tok, diag::err_omp_unexpected_directive) |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 62 | << getOpenMPDirectiveName(DKind); |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 63 | break; |
| 64 | } |
| 65 | SkipUntil(tok::annot_pragma_openmp_end, false); |
| 66 | return DeclGroupPtrTy(); |
| 67 | } |
| 68 | |
| 69 | /// \brief Parses list of simple variables for '#pragma omp threadprivate' |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 70 | /// directive. |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 71 | /// |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 72 | /// simple-variable-list: |
| 73 | /// '(' id-expression {, id-expression} ')' |
| 74 | /// |
| 75 | bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, |
| 76 | SmallVectorImpl<Expr *> &VarList, |
| 77 | bool AllowScopeSpecifier) { |
| 78 | VarList.clear(); |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 79 | // Parse '('. |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 80 | BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); |
| 81 | bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after, |
| 82 | getOpenMPDirectiveName(Kind)); |
| 83 | bool IsCorrect = LParen; |
| 84 | bool NoIdentIsFound = true; |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 85 | |
| 86 | // Read tokens while ')' or annot_pragma_openmp_end is not found. |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 87 | while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 88 | CXXScopeSpec SS; |
| 89 | SourceLocation TemplateKWLoc; |
| 90 | UnqualifiedId Name; |
| 91 | // Read var name. |
| 92 | Token PrevTok = Tok; |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 93 | NoIdentIsFound = false; |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 94 | |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 95 | if (AllowScopeSpecifier && getLangOpts().CPlusPlus && |
| 96 | ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 97 | IsCorrect = false; |
| 98 | SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, |
| 99 | false, true); |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 100 | } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), |
| 101 | TemplateKWLoc, Name)) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 102 | IsCorrect = false; |
| 103 | SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, |
| 104 | false, true); |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 105 | } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && |
| 106 | Tok.isNot(tok::annot_pragma_openmp_end)) { |
| 107 | IsCorrect = false; |
| 108 | SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, |
| 109 | false, true); |
| 110 | Diag(PrevTok.getLocation(), diag::err_expected_ident) |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 111 | << SourceRange(PrevTok.getLocation(), PrevTokLocation); |
| 112 | } else { |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 113 | DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); |
| 114 | ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS, |
| 115 | NameInfo); |
| 116 | if (Res.isUsable()) |
| 117 | VarList.push_back(Res.take()); |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 118 | } |
| 119 | // Consume ','. |
| 120 | if (Tok.is(tok::comma)) { |
| 121 | ConsumeToken(); |
| 122 | } |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 123 | } |
| 124 | |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 125 | if (NoIdentIsFound) { |
| 126 | Diag(Tok, diag::err_expected_ident); |
| 127 | IsCorrect = false; |
| 128 | } |
| 129 | |
| 130 | // Parse ')'. |
| 131 | IsCorrect = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose()) |
| 132 | && IsCorrect; |
| 133 | |
| 134 | return !IsCorrect && VarList.empty(); |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 135 | } |