1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
12 //===----------------------------------------------------------------------===//
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;
20 //===----------------------------------------------------------------------===//
21 // OpenMP declarative directives.
22 //===----------------------------------------------------------------------===//
24 /// \brief Parses OpenMP declarative directive
25 /// threadprivate-directive
26 /// annot_pragma_openmp threadprivate simple-variable-list
28 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
29 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
31 SourceLocation Loc = ConsumeToken();
32 SmallVector<DeclarationNameInfo, 5> Identifiers;
33 OpenMPDirectiveKind Kind = Tok.isAnnotation() ?
35 getOpenMPDirectiveKind(PP.getSpelling(Tok));
37 case OMPD_threadprivate:
39 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) {
40 // The last seen token is annot_pragma_openmp_end - need to check for
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);
48 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
54 Diag(Tok, diag::err_omp_unknown_directive);
57 Diag(Tok, diag::err_omp_unexpected_directive)
58 << getOpenMPDirectiveName(Kind);
61 SkipUntil(tok::annot_pragma_openmp_end, false);
62 return DeclGroupPtrTy();
65 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
67 /// simple-variable-list:
68 /// ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end
70 bool Parser::ParseOpenMPSimpleVarList(
71 OpenMPDirectiveKind Kind,
72 SmallVectorImpl<DeclarationNameInfo> &IdList) {
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);
82 // Read tokens while ')' or annot_pragma_openmp_end is not found.
85 SourceLocation TemplateKWLoc;
90 if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
91 TemplateKWLoc, Name)) {
93 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
96 else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
97 Tok.isNot(tok::annot_pragma_openmp_end)) {
99 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
101 Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id)
102 << getLangOpts().CPlusPlus
103 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
105 IdList.push_back(Actions.GetNameFromUnqualifiedId(Name));
108 if (Tok.is(tok::comma)) {
111 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
113 if (IsCorrect || Tok.is(tok::r_paren)) {
114 IsCorrect = !T.consumeClose() && IsCorrect;
117 return !IsCorrect && IdList.empty();