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" 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} 119