blob: e192ae2e234944de2899b8eb2c85e36a1efc343f [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"
Alexey Bataevc6400582013-03-22 06:34:35 +000015#include "clang/Parse/ParseDiagnostic.h"
Alexey Bataev6af701f2013-05-13 04:18:18 +000016#include "clang/Parse/Parser.h"
17#include "clang/Sema/Scope.h"
18#include "llvm/ADT/PointerIntPair.h"
Alexey Bataevc6400582013-03-22 06:34:35 +000019#include "RAIIObjectsForParser.h"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// OpenMP declarative directives.
24//===----------------------------------------------------------------------===//
25
Alexey Bataev6af701f2013-05-13 04:18:18 +000026/// \brief Parsing of declarative OpenMP directives.
27///
28/// threadprivate-directive:
29/// annot_pragma_openmp 'threadprivate' simple-variable-list
Alexey Bataevc6400582013-03-22 06:34:35 +000030///
31Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
32 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
33
34 SourceLocation Loc = ConsumeToken();
Alexey Bataev6af701f2013-05-13 04:18:18 +000035 SmallVector<Expr *, 5> Identifiers;
36 OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
37 OMPD_unknown :
38 getOpenMPDirectiveKind(PP.getSpelling(Tok));
39
40 switch (DKind) {
Alexey Bataevc6400582013-03-22 06:34:35 +000041 case OMPD_threadprivate:
42 ConsumeToken();
Alexey Bataev6af701f2013-05-13 04:18:18 +000043 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
Alexey Bataevc6400582013-03-22 06:34:35 +000044 // 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 Bataev6af701f2013-05-13 04:18:18 +000051 // Skip the last annot_pragma_openmp_end.
Alexey Bataevc6400582013-03-22 06:34:35 +000052 ConsumeToken();
53 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
Alexey Bataevc6400582013-03-22 06:34:35 +000054 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 Bataev6af701f2013-05-13 04:18:18 +000062 << getOpenMPDirectiveName(DKind);
Alexey Bataevc6400582013-03-22 06:34:35 +000063 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 Bataev6af701f2013-05-13 04:18:18 +000070/// directive.
Alexey Bataevc6400582013-03-22 06:34:35 +000071///
Alexey Bataev6af701f2013-05-13 04:18:18 +000072/// simple-variable-list:
73/// '(' id-expression {, id-expression} ')'
74///
75bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
76 SmallVectorImpl<Expr *> &VarList,
77 bool AllowScopeSpecifier) {
78 VarList.clear();
Alexey Bataevc6400582013-03-22 06:34:35 +000079 // Parse '('.
Alexey Bataev6af701f2013-05-13 04:18:18 +000080 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 Bataevc6400582013-03-22 06:34:35 +000085
86 // Read tokens while ')' or annot_pragma_openmp_end is not found.
Alexey Bataev6af701f2013-05-13 04:18:18 +000087 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
Alexey Bataevc6400582013-03-22 06:34:35 +000088 CXXScopeSpec SS;
89 SourceLocation TemplateKWLoc;
90 UnqualifiedId Name;
91 // Read var name.
92 Token PrevTok = Tok;
Alexey Bataev6af701f2013-05-13 04:18:18 +000093 NoIdentIsFound = false;
Alexey Bataevc6400582013-03-22 06:34:35 +000094
Alexey Bataev6af701f2013-05-13 04:18:18 +000095 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
96 ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
Alexey Bataevc6400582013-03-22 06:34:35 +000097 IsCorrect = false;
98 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
99 false, true);
Alexey Bataev6af701f2013-05-13 04:18:18 +0000100 } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
101 TemplateKWLoc, Name)) {
Alexey Bataevc6400582013-03-22 06:34:35 +0000102 IsCorrect = false;
103 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
104 false, true);
Alexey Bataev6af701f2013-05-13 04:18:18 +0000105 } 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 Bataevc6400582013-03-22 06:34:35 +0000111 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
112 } else {
Alexey Bataev6af701f2013-05-13 04:18:18 +0000113 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 Bataevc6400582013-03-22 06:34:35 +0000118 }
119 // Consume ','.
120 if (Tok.is(tok::comma)) {
121 ConsumeToken();
122 }
Alexey Bataevc6400582013-03-22 06:34:35 +0000123 }
124
Alexey Bataev6af701f2013-05-13 04:18:18 +0000125 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 Bataevc6400582013-03-22 06:34:35 +0000135}