]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / clang / lib / Parse / ParseOpenMP.cpp
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 }