Home | History | Annotate | Download | only in Parse
      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/AST/StmtOpenMP.h"
     16 #include "clang/Parse/ParseDiagnostic.h"
     17 #include "clang/Parse/Parser.h"
     18 #include "clang/Sema/Scope.h"
     19 #include "llvm/ADT/PointerIntPair.h"
     20 #include "RAIIObjectsForParser.h"
     21 using namespace clang;
     22 
     23 //===----------------------------------------------------------------------===//
     24 // OpenMP declarative directives.
     25 //===----------------------------------------------------------------------===//
     26 
     27 /// \brief Parsing of declarative OpenMP directives.
     28 ///
     29 ///       threadprivate-directive:
     30 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
     31 ///
     32 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
     33   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
     34 
     35   SourceLocation Loc = ConsumeToken();
     36   SmallVector<Expr *, 5> Identifiers;
     37   OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
     38                                   OMPD_unknown :
     39                                   getOpenMPDirectiveKind(PP.getSpelling(Tok));
     40 
     41   switch (DKind) {
     42   case OMPD_threadprivate:
     43     ConsumeToken();
     44     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
     45       // The last seen token is annot_pragma_openmp_end - need to check for
     46       // extra tokens.
     47       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
     48         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
     49           << getOpenMPDirectiveName(OMPD_threadprivate);
     50         SkipUntil(tok::annot_pragma_openmp_end, false, true);
     51       }
     52       // Skip the last annot_pragma_openmp_end.
     53       ConsumeToken();
     54       return Actions.ActOnOpenMPThreadprivateDirective(Loc,
     55                                                        Identifiers);
     56     }
     57     break;
     58   case OMPD_unknown:
     59     Diag(Tok, diag::err_omp_unknown_directive);
     60     break;
     61   case OMPD_parallel:
     62   case OMPD_task:
     63   case NUM_OPENMP_DIRECTIVES:
     64     Diag(Tok, diag::err_omp_unexpected_directive)
     65       << getOpenMPDirectiveName(DKind);
     66     break;
     67   }
     68   SkipUntil(tok::annot_pragma_openmp_end, false);
     69   return DeclGroupPtrTy();
     70 }
     71 
     72 /// \brief Parsing of declarative or executable OpenMP directives.
     73 ///
     74 ///       threadprivate-directive:
     75 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
     76 ///         annot_pragma_openmp_end
     77 ///
     78 ///       parallel-directive:
     79 ///         annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
     80 ///
     81 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
     82   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
     83   SmallVector<Expr *, 5> Identifiers;
     84   SmallVector<OMPClause *, 5> Clauses;
     85   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
     86                                                FirstClauses(NUM_OPENMP_CLAUSES);
     87   const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope;
     88   SourceLocation Loc = ConsumeToken(), EndLoc;
     89   OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
     90                                   OMPD_unknown :
     91                                   getOpenMPDirectiveKind(PP.getSpelling(Tok));
     92   StmtResult Directive = StmtError();
     93 
     94   switch (DKind) {
     95   case OMPD_threadprivate:
     96     ConsumeToken();
     97     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
     98       // The last seen token is annot_pragma_openmp_end - need to check for
     99       // extra tokens.
    100       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
    101         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
    102           << getOpenMPDirectiveName(OMPD_threadprivate);
    103         SkipUntil(tok::annot_pragma_openmp_end, false, true);
    104       }
    105       DeclGroupPtrTy Res =
    106         Actions.ActOnOpenMPThreadprivateDirective(Loc,
    107                                                   Identifiers);
    108       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    109     }
    110     SkipUntil(tok::annot_pragma_openmp_end, false);
    111     break;
    112   case OMPD_parallel: {
    113     ConsumeToken();
    114     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    115       OpenMPClauseKind CKind = Tok.isAnnotation() ?
    116                                   OMPC_unknown :
    117                                   getOpenMPClauseKind(PP.getSpelling(Tok));
    118       OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
    119                                             !FirstClauses[CKind].getInt());
    120       FirstClauses[CKind].setInt(true);
    121       if (Clause) {
    122         FirstClauses[CKind].setPointer(Clause);
    123         Clauses.push_back(Clause);
    124       }
    125 
    126       // Skip ',' if any.
    127       if (Tok.is(tok::comma))
    128         ConsumeToken();
    129     }
    130     // End location of the directive.
    131     EndLoc = Tok.getLocation();
    132     // Consume final annot_pragma_openmp_end.
    133     ConsumeToken();
    134 
    135     StmtResult AssociatedStmt;
    136     bool CreateDirective = true;
    137     ParseScope OMPDirectiveScope(this, ScopeFlags);
    138     {
    139       // The body is a block scope like in Lambdas and Blocks.
    140       Sema::CompoundScopeRAII CompoundScope(Actions);
    141       Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 1);
    142       Actions.ActOnStartOfCompoundStmt();
    143       // Parse statement
    144       AssociatedStmt = ParseStatement();
    145       Actions.ActOnFinishOfCompoundStmt();
    146       if (!AssociatedStmt.isUsable()) {
    147         Actions.ActOnCapturedRegionError();
    148         CreateDirective = false;
    149       } else {
    150         AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
    151         CreateDirective = AssociatedStmt.isUsable();
    152       }
    153     }
    154     if (CreateDirective)
    155       Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
    156                                                          AssociatedStmt.take(),
    157                                                          Loc, EndLoc);
    158 
    159     // Exit scope.
    160     OMPDirectiveScope.Exit();
    161     }
    162     break;
    163   case OMPD_unknown:
    164     Diag(Tok, diag::err_omp_unknown_directive);
    165     SkipUntil(tok::annot_pragma_openmp_end, false);
    166     break;
    167   case OMPD_task:
    168   case NUM_OPENMP_DIRECTIVES:
    169     Diag(Tok, diag::err_omp_unexpected_directive)
    170       << getOpenMPDirectiveName(DKind);
    171     SkipUntil(tok::annot_pragma_openmp_end, false);
    172     break;
    173   }
    174   return Directive;
    175 }
    176 
    177 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
    178 /// directive.
    179 ///
    180 ///   simple-variable-list:
    181 ///         '(' id-expression {, id-expression} ')'
    182 ///
    183 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
    184                                       SmallVectorImpl<Expr *> &VarList,
    185                                       bool AllowScopeSpecifier) {
    186   VarList.clear();
    187   // Parse '('.
    188   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    189   if (T.expectAndConsume(diag::err_expected_lparen_after,
    190                          getOpenMPDirectiveName(Kind)))
    191     return true;
    192   bool IsCorrect = true;
    193   bool NoIdentIsFound = true;
    194 
    195   // Read tokens while ')' or annot_pragma_openmp_end is not found.
    196   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    197     CXXScopeSpec SS;
    198     SourceLocation TemplateKWLoc;
    199     UnqualifiedId Name;
    200     // Read var name.
    201     Token PrevTok = Tok;
    202     NoIdentIsFound = false;
    203 
    204     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
    205         ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
    206       IsCorrect = false;
    207       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    208                 false, true);
    209     } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
    210                                   TemplateKWLoc, Name)) {
    211       IsCorrect = false;
    212       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    213                 false, true);
    214     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
    215                Tok.isNot(tok::annot_pragma_openmp_end)) {
    216       IsCorrect = false;
    217       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    218                 false, true);
    219       Diag(PrevTok.getLocation(), diag::err_expected_ident)
    220         << SourceRange(PrevTok.getLocation(), PrevTokLocation);
    221     } else {
    222       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
    223       ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
    224                                                        NameInfo);
    225       if (Res.isUsable())
    226         VarList.push_back(Res.take());
    227     }
    228     // Consume ','.
    229     if (Tok.is(tok::comma)) {
    230       ConsumeToken();
    231     }
    232   }
    233 
    234   if (NoIdentIsFound) {
    235     Diag(Tok, diag::err_expected_ident);
    236     IsCorrect = false;
    237   }
    238 
    239   // Parse ')'.
    240   IsCorrect = !T.consumeClose() && IsCorrect;
    241 
    242   return !IsCorrect && VarList.empty();
    243 }
    244 
    245 /// \brief Parsing of OpenMP clauses.
    246 ///
    247 ///    clause:
    248 ///       default-clause|private-clause
    249 ///
    250 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
    251                                      OpenMPClauseKind CKind, bool FirstClause) {
    252   OMPClause *Clause = 0;
    253   bool ErrorFound = false;
    254   // Check if clause is allowed for the given directive.
    255   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
    256     Diag(Tok, diag::err_omp_unexpected_clause)
    257       << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
    258     ErrorFound = true;
    259   }
    260 
    261   switch (CKind) {
    262   case OMPC_default:
    263     // OpenMP [2.9.3.1, Restrictions]
    264     //  Only a single default clause may be specified on a parallel or task
    265     //  directive.
    266     if (!FirstClause) {
    267       Diag(Tok, diag::err_omp_more_one_clause)
    268            << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
    269     }
    270 
    271     Clause = ParseOpenMPSimpleClause(CKind);
    272     break;
    273   case OMPC_private:
    274     Clause = ParseOpenMPVarListClause(CKind);
    275     break;
    276   case OMPC_unknown:
    277     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
    278       << getOpenMPDirectiveName(DKind);
    279     SkipUntil(tok::annot_pragma_openmp_end, false, true);
    280     break;
    281   case OMPC_threadprivate:
    282   case NUM_OPENMP_CLAUSES:
    283     Diag(Tok, diag::err_omp_unexpected_clause)
    284       << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
    285     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, false, true);
    286     break;
    287   }
    288   return ErrorFound ? 0 : Clause;
    289 }
    290 
    291 /// \brief Parsing of simple OpenMP clauses like 'default'.
    292 ///
    293 ///    default-clause:
    294 ///         'default' '(' 'none' | 'shared' ')
    295 ///
    296 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
    297   SourceLocation Loc = Tok.getLocation();
    298   SourceLocation LOpen = ConsumeToken();
    299   // Parse '('.
    300   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    301   if (T.expectAndConsume(diag::err_expected_lparen_after,
    302                          getOpenMPClauseName(Kind)))
    303     return 0;
    304 
    305   unsigned Type = Tok.isAnnotation() ?
    306                      unsigned(OMPC_DEFAULT_unknown) :
    307                      getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
    308   SourceLocation TypeLoc = Tok.getLocation();
    309   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
    310       Tok.isNot(tok::annot_pragma_openmp_end))
    311     ConsumeAnyToken();
    312 
    313   // Parse ')'.
    314   T.consumeClose();
    315 
    316   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
    317                                          Tok.getLocation());
    318 }
    319 
    320 /// \brief Parsing of OpenMP clause 'private', 'firstprivate',
    321 /// 'shared', 'copyin', or 'reduction'.
    322 ///
    323 ///    private-clause:
    324 ///       'private' '(' list ')'
    325 ///
    326 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
    327   SourceLocation Loc = Tok.getLocation();
    328   SourceLocation LOpen = ConsumeToken();
    329   // Parse '('.
    330   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    331   if (T.expectAndConsume(diag::err_expected_lparen_after,
    332                          getOpenMPClauseName(Kind)))
    333     return 0;
    334 
    335   SmallVector<Expr *, 5> Vars;
    336   bool IsComma = true;
    337   while (IsComma || (Tok.isNot(tok::r_paren) &&
    338                      Tok.isNot(tok::annot_pragma_openmp_end))) {
    339     // Parse variable
    340     ExprResult VarExpr = ParseAssignmentExpression();
    341     if (VarExpr.isUsable()) {
    342       Vars.push_back(VarExpr.take());
    343     } else {
    344       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    345                 false, true);
    346     }
    347     // Skip ',' if any
    348     IsComma = Tok.is(tok::comma);
    349     if (IsComma) {
    350       ConsumeToken();
    351     } else if (Tok.isNot(tok::r_paren) &&
    352                Tok.isNot(tok::annot_pragma_openmp_end)) {
    353       Diag(Tok, diag::err_omp_expected_punc)
    354         << 1 << getOpenMPClauseName(Kind);
    355     }
    356   }
    357 
    358   // Parse ')'.
    359   T.consumeClose();
    360   if (Vars.empty())
    361     return 0;
    362 
    363   return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
    364                                           Tok.getLocation());
    365 }
    366 
    367