/// \brief Consume tokens and store them in the passed token container until
/// we've passed the try keyword and constructor initializers and have consumed
/// the opening brace of the function body. The opening brace will be consumed
/// if and only if there was no error.
///
/// \return True on error. 
bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
  if (Tok.is(tok::kw_try)) {
    Toks.push_back(Tok);
    ConsumeToken();
  }
  if (Tok.is(tok::colon)) {
    // Initializers can contain braces too.
    Toks.push_back(Tok);
    ConsumeToken();

    while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
      if (Tok.is(tok::eof) || Tok.is(tok::semi))
        return true;

      // Grab the identifier.
      if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,
                                /*StopAtSemi=*/true,
                                /*ConsumeFinalToken=*/false))
        return true;

      tok::TokenKind kind = Tok.getKind();
      Toks.push_back(Tok);
      if (kind == tok::l_paren)
        ConsumeParen();
      else {
        assert(kind == tok::l_brace && "Must be left paren or brace here.");
        ConsumeBrace();
        // In C++03, this has to be the start of the function body, which
        // means the initializer is malformed.
        if (!getLang().CPlusPlus0x)
          return false;
      }

      // Grab the initializer
      if (!ConsumeAndStoreUntil(kind == tok::l_paren ? tok::r_paren :
                                                       tok::r_brace,
                                Toks, /*StopAtSemi=*/true))
        return true;

      // Grab the separating comma, if any.
      if (Tok.is(tok::comma)) {
        Toks.push_back(Tok);
        ConsumeToken();
      }
    }
  }

  // Grab any remaining garbage to be diagnosed later. We stop when we reach a
  // brace: an opening one is the function body, while a closing one probably
  // means we've reached the end of the class.
  if (!ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
                            /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false))
    return true;
  if(Tok.isNot(tok::l_brace))
    return true;

  Toks.push_back(Tok);
  ConsumeBrace();
  return false;
}
/// \brief Consume and store tokens from the '?' to the ':' in a conditional
/// expression.
bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) {
  // Consume '?'.
  assert(Tok.is(tok::question));
  Toks.push_back(Tok);
  ConsumeToken();

  while (Tok.isNot(tok::colon)) {
    if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks, /*StopAtSemi*/true,
                              /*ConsumeFinalToken*/false))
      return false;

    // If we found a nested conditional, consume it.
    if (Tok.is(tok::question) && !ConsumeAndStoreConditional(Toks))
      return false;
  }

  // Consume ':'.
  Toks.push_back(Tok);
  ConsumeToken();
  return true;
}
示例#3
0
/// \brief Lex a delayed template function for late parsing.
void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {
  tok::TokenKind kind = Tok.getKind();
  // We may have a constructor initializer or function-try-block here.
  if (kind == tok::colon || kind == tok::kw_try)
    ConsumeAndStoreUntil(tok::l_brace, Toks);
  else {
    Toks.push_back(Tok);
    ConsumeBrace();
  }
  // Consume everything up to (and including) the matching right brace.
  ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);

  // If we're in a function-try-block, we need to store all the catch blocks.
  if (kind == tok::kw_try) {
    while (Tok.is(tok::kw_catch)) {
      ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
      ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
    }
  }
}
示例#4
0
/// \brief Consume tokens and store them in the passed token container until
/// we've passed the try keyword and constructor initializers and have consumed
/// the opening brace of the function body. The opening brace will be consumed
/// if and only if there was no error.
///
/// \return True on error. 
bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
  if (Tok.is(tok::kw_try)) {
    Toks.push_back(Tok);
    ConsumeToken();
  }
  bool ReadInitializer = false;
  if (Tok.is(tok::colon)) {
    // Initializers can contain braces too.
    Toks.push_back(Tok);
    ConsumeToken();

    while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
      if (Tok.is(tok::eof) || Tok.is(tok::semi))
        return Diag(Tok.getLocation(), diag::err_expected_lbrace);

      // Grab the identifier.
      if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,
                                /*StopAtSemi=*/true,
                                /*ConsumeFinalToken=*/false))
        return Diag(Tok.getLocation(), diag::err_expected_lparen);

      tok::TokenKind kind = Tok.getKind();
      Toks.push_back(Tok);
      bool IsLParen = (kind == tok::l_paren);
      SourceLocation LOpen = Tok.getLocation();

      if (IsLParen) {
        ConsumeParen();
      } else {
        assert(kind == tok::l_brace && "Must be left paren or brace here.");
        ConsumeBrace();
        // In C++03, this has to be the start of the function body, which
        // means the initializer is malformed; we'll diagnose it later.
        if (!getLangOpts().CPlusPlus11)
          return false;
      }

      // Grab the initializer
      if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace,
                                Toks, /*StopAtSemi=*/true)) {
        Diag(Tok, IsLParen ? diag::err_expected_rparen :
                             diag::err_expected_rbrace);
        Diag(LOpen, diag::note_matching) << (IsLParen ? "(" : "{");
        return true;
      }

      // Grab pack ellipsis, if present
      if (Tok.is(tok::ellipsis)) {
        Toks.push_back(Tok);
        ConsumeToken();
      }

      // Grab the separating comma, if any.
      if (Tok.is(tok::comma)) {
        Toks.push_back(Tok);
        ConsumeToken();
      } else if (Tok.isNot(tok::l_brace)) {
        ReadInitializer = true;
        break;
      }
    }
  }

  // Grab any remaining garbage to be diagnosed later. We stop when we reach a
  // brace: an opening one is the function body, while a closing one probably
  // means we've reached the end of the class.
  ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
                       /*StopAtSemi=*/true,
                       /*ConsumeFinalToken=*/false);
  if (Tok.isNot(tok::l_brace)) {
    if (ReadInitializer)
      return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
    return Diag(Tok.getLocation(), diag::err_expected_lbrace);
  }

  Toks.push_back(Tok);
  ConsumeBrace();
  return false;
}
示例#5
0
/// ConsumeAndStoreUntil - Consume and store the token at the passed token
/// container until the token 'T' is reached (which gets
/// consumed/stored too, if ConsumeFinalToken).
/// If StopAtSemi is true, then we will stop early at a ';' character.
/// Returns true if token 'T1' or 'T2' was found.
/// NOTE: This is a specialized version of Parser::SkipUntil.
bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
                                  CachedTokens &Toks,
                                  bool StopAtSemi, bool ConsumeFinalToken) {
  // We always want this function to consume at least one token if the first
  // token isn't T and if not at EOF.
  bool isFirstTokenConsumed = true;
  while (1) {
    // If we found one of the tokens, stop and return true.
    if (Tok.is(T1) || Tok.is(T2)) {
      if (ConsumeFinalToken) {
        Toks.push_back(Tok);
        ConsumeAnyToken();
      }
      return true;
    }

    switch (Tok.getKind()) {
    case tok::eof:
      // Ran out of tokens.
      return false;

    case tok::l_paren:
      // Recursively consume properly-nested parens.
      Toks.push_back(Tok);
      ConsumeParen();
      ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
      break;
    case tok::l_square:
      // Recursively consume properly-nested square brackets.
      Toks.push_back(Tok);
      ConsumeBracket();
      ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
      break;
    case tok::l_brace:
      // Recursively consume properly-nested braces.
      Toks.push_back(Tok);
      ConsumeBrace();
      ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
      break;

    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
    // Since the user wasn't looking for this token (if they were, it would
    // already be handled), this isn't balanced.  If there is a LHS token at a
    // higher level, we will assume that this matches the unbalanced token
    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
    case tok::r_paren:
      if (ParenCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeParen();
      break;
    case tok::r_square:
      if (BracketCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeBracket();
      break;
    case tok::r_brace:
      if (BraceCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeBrace();
      break;

    case tok::code_completion:
      Toks.push_back(Tok);
      ConsumeCodeCompletionToken();
      break;

    case tok::string_literal:
    case tok::wide_string_literal:
    case tok::utf8_string_literal:
    case tok::utf16_string_literal:
    case tok::utf32_string_literal:
      Toks.push_back(Tok);
      ConsumeStringToken();
      break;
    case tok::semi:
      if (StopAtSemi)
        return false;
      // FALL THROUGH.
    default:
      // consume this token.
      Toks.push_back(Tok);
      ConsumeToken();
      break;
    }
    isFirstTokenConsumed = false;
  }
}
/// ConsumeAndStoreInitializer - Consume and store the token at the passed token
/// container until the end of the current initializer expression (either a
/// default argument or an in-class initializer for a non-static data member).
///
/// Returns \c true if we reached the end of something initializer-shaped,
/// \c false if we bailed out.
bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
                                        CachedInitKind CIK) {
  // We always want this function to consume at least one token if not at EOF.
  bool IsFirstToken = true;

  // Number of possible unclosed <s we've seen so far. These might be templates,
  // and might not, but if there were none of them (or we know for sure that
  // we're within a template), we can avoid a tentative parse.
  unsigned AngleCount = 0;
  unsigned KnownTemplateCount = 0;

  while (1) {
    switch (Tok.getKind()) {
    case tok::comma:
      // If we might be in a template, perform a tentative parse to check.
      if (!AngleCount)
        // Not a template argument: this is the end of the initializer.
        return true;
      if (KnownTemplateCount)
        goto consume_token;

      // We hit a comma inside angle brackets. This is the hard case. The
      // rule we follow is:
      //  * For a default argument, if the tokens after the comma form a
      //    syntactically-valid parameter-declaration-clause, in which each
      //    parameter has an initializer, then this comma ends the default
      //    argument.
      //  * For a default initializer, if the tokens after the comma form a
      //    syntactically-valid init-declarator-list, then this comma ends
      //    the default initializer.
      {
        UnannotatedTentativeParsingAction PA(*this,
                                             CIK == CIK_DefaultInitializer
                                               ? tok::semi : tok::r_paren);
        Sema::TentativeAnalysisScope Scope(Actions);

        TPResult Result = TPResult::Error;
        ConsumeToken();
        switch (CIK) {
        case CIK_DefaultInitializer:
          Result = TryParseInitDeclaratorList();
          // If we parsed a complete, ambiguous init-declarator-list, this
          // is only syntactically-valid if it's followed by a semicolon.
          if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi))
            Result = TPResult::False;
          break;

        case CIK_DefaultArgument:
          bool InvalidAsDeclaration = false;
          Result = TryParseParameterDeclarationClause(
              &InvalidAsDeclaration, /*VersusTemplateArgument=*/true);
          // If this is an expression or a declaration with a missing
          // 'typename', assume it's not a declaration.
          if (Result == TPResult::Ambiguous && InvalidAsDeclaration)
            Result = TPResult::False;
          break;
        }

        // If what follows could be a declaration, it is a declaration.
        if (Result != TPResult::False && Result != TPResult::Error) {
          PA.Revert();
          return true;
        }

        // In the uncommon case that we decide the following tokens are part
        // of a template argument, revert any annotations we've performed in
        // those tokens. We're not going to look them up until we've parsed
        // the rest of the class, and that might add more declarations.
        PA.RevertAnnotations();
      }

      // Keep going. We know we're inside a template argument list now.
      ++KnownTemplateCount;
      goto consume_token;

    case tok::eof:
    case tok::annot_module_begin:
    case tok::annot_module_end:
    case tok::annot_module_include:
      // Ran out of tokens.
      return false;

    case tok::less:
      // FIXME: A '<' can only start a template-id if it's preceded by an
      // identifier, an operator-function-id, or a literal-operator-id.
      ++AngleCount;
      goto consume_token;

    case tok::question:
      // In 'a ? b : c', 'b' can contain an unparenthesized comma. If it does,
      // that is *never* the end of the initializer. Skip to the ':'.
      if (!ConsumeAndStoreConditional(Toks))
        return false;
      break;

    case tok::greatergreatergreater:
      if (!getLangOpts().CPlusPlus11)
        goto consume_token;
      if (AngleCount) --AngleCount;
      if (KnownTemplateCount) --KnownTemplateCount;
      // Fall through.
    case tok::greatergreater:
      if (!getLangOpts().CPlusPlus11)
        goto consume_token;
      if (AngleCount) --AngleCount;
      if (KnownTemplateCount) --KnownTemplateCount;
      // Fall through.
    case tok::greater:
      if (AngleCount) --AngleCount;
      if (KnownTemplateCount) --KnownTemplateCount;
      goto consume_token;

    case tok::kw_template:
      // 'template' identifier '<' is known to start a template argument list,
      // and can be used to disambiguate the parse.
      // FIXME: Support all forms of 'template' unqualified-id '<'.
      Toks.push_back(Tok);
      ConsumeToken();
      if (Tok.is(tok::identifier)) {
        Toks.push_back(Tok);
        ConsumeToken();
        if (Tok.is(tok::less)) {
          ++AngleCount;
          ++KnownTemplateCount;
          Toks.push_back(Tok);
          ConsumeToken();
        }
      }
      break;

    case tok::kw_operator:
      // If 'operator' precedes other punctuation, that punctuation loses
      // its special behavior.
      Toks.push_back(Tok);
      ConsumeToken();
      switch (Tok.getKind()) {
      case tok::comma:
      case tok::greatergreatergreater:
      case tok::greatergreater:
      case tok::greater:
      case tok::less:
        Toks.push_back(Tok);
        ConsumeToken();
        break;
      default:
        break;
      }
      break;

    case tok::l_paren:
      // Recursively consume properly-nested parens.
      Toks.push_back(Tok);
      ConsumeParen();
      ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
      break;
    case tok::l_square:
      // Recursively consume properly-nested square brackets.
      Toks.push_back(Tok);
      ConsumeBracket();
      ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
      break;
    case tok::l_brace:
      // Recursively consume properly-nested braces.
      Toks.push_back(Tok);
      ConsumeBrace();
      ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
      break;

    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
    // Since the user wasn't looking for this token (if they were, it would
    // already be handled), this isn't balanced.  If there is a LHS token at a
    // higher level, we will assume that this matches the unbalanced token
    // and return it.  Otherwise, this is a spurious RHS token, which we
    // consume and pass on to downstream code to diagnose.
    case tok::r_paren:
      if (CIK == CIK_DefaultArgument)
        return true; // End of the default argument.
      if (ParenCount && !IsFirstToken)
        return false;
      Toks.push_back(Tok);
      ConsumeParen();
      continue;
    case tok::r_square:
      if (BracketCount && !IsFirstToken)
        return false;
      Toks.push_back(Tok);
      ConsumeBracket();
      continue;
    case tok::r_brace:
      if (BraceCount && !IsFirstToken)
        return false;
      Toks.push_back(Tok);
      ConsumeBrace();
      continue;

    case tok::code_completion:
      Toks.push_back(Tok);
      ConsumeCodeCompletionToken();
      break;

    case tok::string_literal:
    case tok::wide_string_literal:
    case tok::utf8_string_literal:
    case tok::utf16_string_literal:
    case tok::utf32_string_literal:
      Toks.push_back(Tok);
      ConsumeStringToken();
      break;
    case tok::semi:
      if (CIK == CIK_DefaultInitializer)
        return true; // End of the default initializer.
      // FALL THROUGH.
    default:
    consume_token:
      Toks.push_back(Tok);
      ConsumeToken();
      break;
    }
    IsFirstToken = false;
  }
}
/// \brief Consume tokens and store them in the passed token container until
/// we've passed the try keyword and constructor initializers and have consumed
/// the opening brace of the function body. The opening brace will be consumed
/// if and only if there was no error.
///
/// \return True on error.
bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
  if (Tok.is(tok::kw_try)) {
    Toks.push_back(Tok);
    ConsumeToken();
  }

  if (Tok.isNot(tok::colon)) {
    // Easy case, just a function body.

    // Grab any remaining garbage to be diagnosed later. We stop when we reach a
    // brace: an opening one is the function body, while a closing one probably
    // means we've reached the end of the class.
    ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
                         /*StopAtSemi=*/true,
                         /*ConsumeFinalToken=*/false);
    if (Tok.isNot(tok::l_brace))
      return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;

    Toks.push_back(Tok);
    ConsumeBrace();
    return false;
  }

  Toks.push_back(Tok);
  ConsumeToken();

  // We can't reliably skip over a mem-initializer-id, because it could be
  // a template-id involving not-yet-declared names. Given:
  //
  //   S ( ) : a < b < c > ( e )
  //
  // 'e' might be an initializer or part of a template argument, depending
  // on whether 'b' is a template.

  // Track whether we might be inside a template argument. We can give
  // significantly better diagnostics if we know that we're not.
  bool MightBeTemplateArgument = false;

  while (true) {
    // Skip over the mem-initializer-id, if possible.
    if (Tok.is(tok::kw_decltype)) {
      Toks.push_back(Tok);
      SourceLocation OpenLoc = ConsumeToken();
      if (Tok.isNot(tok::l_paren))
        return Diag(Tok.getLocation(), diag::err_expected_lparen_after)
                 << "decltype";
      Toks.push_back(Tok);
      ConsumeParen();
      if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) {
        Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
        Diag(OpenLoc, diag::note_matching) << tok::l_paren;
        return true;
      }
    }
    do {
      // Walk over a component of a nested-name-specifier.
      if (Tok.is(tok::coloncolon)) {
        Toks.push_back(Tok);
        ConsumeToken();

        if (Tok.is(tok::kw_template)) {
          Toks.push_back(Tok);
          ConsumeToken();
        }
      }

      if (Tok.is(tok::identifier) || Tok.is(tok::kw_template)) {
        Toks.push_back(Tok);
        ConsumeToken();
      } else if (Tok.is(tok::code_completion)) {
        Toks.push_back(Tok);
        ConsumeCodeCompletionToken();
        // Consume the rest of the initializers permissively.
        // FIXME: We should be able to perform code-completion here even if
        //        there isn't a subsequent '{' token.
        MightBeTemplateArgument = true;
        break;
      } else {
        break;
      }
    } while (Tok.is(tok::coloncolon));

    if (Tok.is(tok::less))
      MightBeTemplateArgument = true;

    if (MightBeTemplateArgument) {
      // We may be inside a template argument list. Grab up to the start of the
      // next parenthesized initializer or braced-init-list. This *might* be the
      // initializer, or it might be a subexpression in the template argument
      // list.
      // FIXME: Count angle brackets, and clear MightBeTemplateArgument
      //        if all angles are closed.
      if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,
                                /*StopAtSemi=*/true,
                                /*ConsumeFinalToken=*/false)) {
        // We're not just missing the initializer, we're also missing the
        // function body!
        return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
      }
    } else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) {
      // We found something weird in a mem-initializer-id.
      if (getLangOpts().CPlusPlus11)
        return Diag(Tok.getLocation(), diag::err_expected_either)
               << tok::l_paren << tok::l_brace;
      else
        return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
    }

    tok::TokenKind kind = Tok.getKind();
    Toks.push_back(Tok);
    bool IsLParen = (kind == tok::l_paren);
    SourceLocation OpenLoc = Tok.getLocation();

    if (IsLParen) {
      ConsumeParen();
    } else {
      assert(kind == tok::l_brace && "Must be left paren or brace here.");
      ConsumeBrace();
      // In C++03, this has to be the start of the function body, which
      // means the initializer is malformed; we'll diagnose it later.
      if (!getLangOpts().CPlusPlus11)
        return false;
    }

    // Grab the initializer (or the subexpression of the template argument).
    // FIXME: If we support lambdas here, we'll need to set StopAtSemi to false
    //        if we might be inside the braces of a lambda-expression.
    tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace;
    if (!ConsumeAndStoreUntil(CloseKind, Toks, /*StopAtSemi=*/true)) {
      Diag(Tok, diag::err_expected) << CloseKind;
      Diag(OpenLoc, diag::note_matching) << kind;
      return true;
    }

    // Grab pack ellipsis, if present.
    if (Tok.is(tok::ellipsis)) {
      Toks.push_back(Tok);
      ConsumeToken();
    }

    // If we know we just consumed a mem-initializer, we must have ',' or '{'
    // next.
    if (Tok.is(tok::comma)) {
      Toks.push_back(Tok);
      ConsumeToken();
    } else if (Tok.is(tok::l_brace)) {
      // This is the function body if the ')' or '}' is immediately followed by
      // a '{'. That cannot happen within a template argument, apart from the
      // case where a template argument contains a compound literal:
      //
      //   S ( ) : a < b < c > ( d ) { }
      //   // End of declaration, or still inside the template argument?
      //
      // ... and the case where the template argument contains a lambda:
      //
      //   S ( ) : a < 0 && b < c > ( d ) + [ ] ( ) { return 0; }
      //     ( ) > ( ) { }
      //
      // FIXME: Disambiguate these cases. Note that the latter case is probably
      //        going to be made ill-formed by core issue 1607.
      Toks.push_back(Tok);
      ConsumeBrace();
      return false;
    } else if (!MightBeTemplateArgument) {
      return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
                                                                << tok::comma;
    }
  }
}