blob: 507a6b1bcd8727b4893ba9b222369cbdd70bfb52 [file] [log] [blame]
Alexey Bataevc6400582013-03-22 06:34:35 +00001//===--- 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"
18using 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///
28Parser::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///
70bool 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}