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" |
| 15 | #include "clang/Parse/Parser.h" |
| 16 | #include "clang/Parse/ParseDiagnostic.h" |
| 17 | #include "RAIIObjectsForParser.h" |
| 18 | using namespace clang; |
| 19 | |
| 20 | //===----------------------------------------------------------------------===// |
| 21 | // OpenMP declarative directives. |
| 22 | //===----------------------------------------------------------------------===// |
| 23 | |
| 24 | /// \brief Parses OpenMP declarative directive |
| 25 | /// threadprivate-directive |
| 26 | /// annot_pragma_openmp threadprivate simple-variable-list |
| 27 | /// |
| 28 | Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { |
| 29 | assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); |
| 30 | |
| 31 | SourceLocation Loc = ConsumeToken(); |
| 32 | SmallVector<DeclarationNameInfo, 5> Identifiers; |
| 33 | OpenMPDirectiveKind Kind = Tok.isAnnotation() ? |
| 34 | OMPD_unknown : |
| 35 | getOpenMPDirectiveKind(PP.getSpelling(Tok)); |
| 36 | switch(Kind) { |
| 37 | case OMPD_threadprivate: |
| 38 | ConsumeToken(); |
| 39 | if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) { |
| 40 | // The last seen token is annot_pragma_openmp_end - need to check for |
| 41 | // extra tokens. |
| 42 | if (Tok.isNot(tok::annot_pragma_openmp_end)) { |
| 43 | Diag(Tok, diag::warn_omp_extra_tokens_at_eol) |
| 44 | << getOpenMPDirectiveName(OMPD_threadprivate); |
| 45 | SkipUntil(tok::annot_pragma_openmp_end, false, true); |
| 46 | } |
| 47 | ConsumeToken(); |
| 48 | return Actions.ActOnOpenMPThreadprivateDirective(Loc, |
| 49 | getCurScope(), |
| 50 | Identifiers); |
| 51 | } |
| 52 | break; |
| 53 | case OMPD_unknown: |
| 54 | Diag(Tok, diag::err_omp_unknown_directive); |
| 55 | break; |
| 56 | default: |
| 57 | Diag(Tok, diag::err_omp_unexpected_directive) |
| 58 | << getOpenMPDirectiveName(Kind); |
| 59 | break; |
| 60 | } |
| 61 | SkipUntil(tok::annot_pragma_openmp_end, false); |
| 62 | return DeclGroupPtrTy(); |
| 63 | } |
| 64 | |
| 65 | /// \brief Parses list of simple variables for '#pragma omp threadprivate' |
| 66 | /// directive |
| 67 | /// simple-variable-list: |
| 68 | /// ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end |
| 69 | /// |
| 70 | bool Parser::ParseOpenMPSimpleVarList( |
| 71 | OpenMPDirectiveKind Kind, |
| 72 | SmallVectorImpl<DeclarationNameInfo> &IdList) { |
| 73 | // Parse '('. |
| 74 | bool IsCorrect = true; |
| 75 | BalancedDelimiterTracker T(*this, tok::l_paren); |
| 76 | if (T.expectAndConsume(diag::err_expected_lparen_after, |
| 77 | getOpenMPDirectiveName(Kind))) { |
| 78 | SkipUntil(tok::annot_pragma_openmp_end, false, true); |
| 79 | return false; |
| 80 | } |
| 81 | |
| 82 | // Read tokens while ')' or annot_pragma_openmp_end is not found. |
| 83 | do { |
| 84 | CXXScopeSpec SS; |
| 85 | SourceLocation TemplateKWLoc; |
| 86 | UnqualifiedId Name; |
| 87 | // Read var name. |
| 88 | Token PrevTok = Tok; |
| 89 | |
| 90 | if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), |
| 91 | TemplateKWLoc, Name)) { |
| 92 | IsCorrect = false; |
| 93 | SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, |
| 94 | false, true); |
| 95 | } |
| 96 | else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && |
| 97 | Tok.isNot(tok::annot_pragma_openmp_end)) { |
| 98 | IsCorrect = false; |
| 99 | SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, |
| 100 | false, true); |
| 101 | Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id) |
| 102 | << getLangOpts().CPlusPlus |
| 103 | << SourceRange(PrevTok.getLocation(), PrevTokLocation); |
| 104 | } else { |
| 105 | IdList.push_back(Actions.GetNameFromUnqualifiedId(Name)); |
| 106 | } |
| 107 | // Consume ','. |
| 108 | if (Tok.is(tok::comma)) { |
| 109 | ConsumeToken(); |
| 110 | } |
| 111 | } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); |
| 112 | |
| 113 | if (IsCorrect || Tok.is(tok::r_paren)) { |
| 114 | IsCorrect = !T.consumeClose() && IsCorrect; |
| 115 | } |
| 116 | |
| 117 | return !IsCorrect && IdList.empty(); |
| 118 | } |