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/ParseDiagnostic.h" 16 #include "clang/Parse/Parser.h" 17 #include "clang/Sema/Scope.h" 18 #include "llvm/ADT/PointerIntPair.h" 19 #include "RAIIObjectsForParser.h" 20 using namespace clang; 21 22 //===----------------------------------------------------------------------===// 23 // OpenMP declarative directives. 24 //===----------------------------------------------------------------------===// 25 26 /// \brief Parsing of declarative OpenMP directives. 27 /// 28 /// threadprivate-directive: 29 /// annot_pragma_openmp 'threadprivate' simple-variable-list 30 /// 31 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { 32 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 33 34 SourceLocation Loc = ConsumeToken(); 35 SmallVector<Expr *, 5> Identifiers; 36 OpenMPDirectiveKind DKind = Tok.isAnnotation() ? 37 OMPD_unknown : 38 getOpenMPDirectiveKind(PP.getSpelling(Tok)); 39 40 switch (DKind) { 41 case OMPD_threadprivate: 42 ConsumeToken(); 43 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) { 44 // 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 } 51 // Skip the last annot_pragma_openmp_end. 52 ConsumeToken(); 53 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 54 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) 62 << getOpenMPDirectiveName(DKind); 63 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' 70 /// directive. 71 /// 72 /// simple-variable-list: 73 /// '(' id-expression {, id-expression} ')' 74 /// 75 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, 76 SmallVectorImpl<Expr *> &VarList, 77 bool AllowScopeSpecifier) { 78 VarList.clear(); 79 // Parse '('. 80 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; 85 86 // Read tokens while ')' or annot_pragma_openmp_end is not found. 87 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 88 CXXScopeSpec SS; 89 SourceLocation TemplateKWLoc; 90 UnqualifiedId Name; 91 // Read var name. 92 Token PrevTok = Tok; 93 NoIdentIsFound = false; 94 95 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 96 ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) { 97 IsCorrect = false; 98 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 99 false, true); 100 } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), 101 TemplateKWLoc, Name)) { 102 IsCorrect = false; 103 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 104 false, true); 105 } 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) 111 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 112 } else { 113 DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); 114 ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS, 115 NameInfo); 116 if (Res.isUsable()) 117 VarList.push_back(Res.take()); 118 } 119 // Consume ','. 120 if (Tok.is(tok::comma)) { 121 ConsumeToken(); 122 } 123 } 124 125 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(); 135 } 136