diff options
| author | John McCall <rjmccall@apple.com> | 2010-02-26 08:45:28 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-02-26 08:45:28 +0000 | 
| commit | 1f476a1783d95d9b53b10f763789e8afeded42f3 (patch) | |
| tree | ef4171febd99b0f182fd41f0569b0f83d1b006bc /clang/lib/Parse | |
| parent | 663f658d87961061a191611ce4a8ec3f32df296f (diff) | |
| download | bcm5719-llvm-1f476a1783d95d9b53b10f763789e8afeded42f3.tar.gz bcm5719-llvm-1f476a1783d95d9b53b10f763789e8afeded42f3.zip  | |
Fix an assertion-on-error during tentative constructor parsing by
propagating error conditions out of the various annotate-me-a-snowflake
routines.  Generally (but not universally) removes redundant diagnostics
as well as, you know, not crashing on bad code.  On the other hand,
I have just signed myself up to fix fiddly parser errors for the next
week.  Again.
llvm-svn: 97221
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 96 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 40 | 
6 files changed, 107 insertions, 75 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 62b10a316e6..5dc4bd2f609 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -859,10 +859,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,        return;      case tok::coloncolon: // ::foo::bar -      // Annotate C++ scope specifiers.  If we get one, loop. -      if (TryAnnotateCXXScopeToken(true)) -        continue; -      goto DoneWithDeclSpec; +      // C++ scope specifier.  Annotate and loop, or bail out on error. +      if (TryAnnotateCXXScopeToken(true)) { +        if (!DS.hasTypeSpecifier()) +          DS.SetTypeSpecError(); +        goto DoneWithDeclSpec; +      } +      continue;      case tok::annot_cxxscope: {        if (DS.hasTypeSpecifier()) @@ -1020,8 +1023,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,      case tok::identifier: {        // In C++, check to see if this is a scope specifier like foo::bar::, if        // so handle it as such.  This is important for ctor parsing. -      if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true)) -        continue; +      if (getLang().CPlusPlus) { +        if (TryAnnotateCXXScopeToken(true)) { +          if (!DS.hasTypeSpecifier()) +            DS.SetTypeSpecError(); +          goto DoneWithDeclSpec; +        } +        if (!Tok.is(tok::identifier)) +          continue; +      }        // This identifier can only be a typedef name if we haven't already seen        // a type-specifier.  Without this check we misparse: @@ -1313,7 +1323,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,      // C++ typename-specifier:      case tok::kw_typename: -      if (TryAnnotateTypeOrScopeToken()) +      if (TryAnnotateTypeOrScopeToken()) { +        DS.SetTypeSpecError(); +        goto DoneWithDeclSpec; +      } +      if (!Tok.is(tok::kw_typename))          continue;        break; @@ -1423,10 +1437,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, -                                        TemplateInfo, SuppressDeclarations); -    // Otherwise, not a type specifier. -    return false; +      return true; +    if (Tok.is(tok::identifier)) +      return false; +    return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, +                                      TemplateInfo, SuppressDeclarations);    case tok::coloncolon:   // ::foo::bar      if (NextToken().is(tok::kw_new) ||    // ::new          NextToken().is(tok::kw_delete))   // ::delete @@ -1435,10 +1450,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, -                                        TemplateInfo, SuppressDeclarations); -    // Otherwise, not a type specifier. -    return false; +      return true; +    return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, +                                      TemplateInfo, SuppressDeclarations);    // simple-type-specifier:    case tok::annot_typename: { @@ -1848,8 +1862,11 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,      Attr.reset(ParseGNUAttributes());    CXXScopeSpec SS; -  if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) { -    if (Tok.isNot(tok::identifier)) { +  if (getLang().CPlusPlus) { +    if (ParseOptionalCXXScopeSpecifier(SS, 0, false)) +      return; + +    if (SS.isSet() && Tok.isNot(tok::identifier)) {        Diag(Tok, diag::err_expected_ident);        if (Tok.isNot(tok::l_brace)) {          // Has no name and is not a definition. @@ -2016,21 +2033,19 @@ bool Parser::isTypeSpecifierQualifier() {      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return isTypeSpecifierQualifier(); -    // Otherwise, not a type specifier. -    return false; +      return true; +    if (Tok.is(tok::identifier)) +      return false; +    return isTypeSpecifierQualifier();    case tok::coloncolon:   // ::foo::bar      if (NextToken().is(tok::kw_new) ||    // ::new          NextToken().is(tok::kw_delete))   // ::delete        return false; -    // Annotate typenames and C++ scope specifiers.  If we get one, just -    // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return isTypeSpecifierQualifier(); -    // Otherwise, not a type specifier. -    return false; +      return true; +    return isTypeSpecifierQualifier();      // GNU attributes support.    case tok::kw___attribute: @@ -2101,14 +2116,15 @@ bool Parser::isDeclarationSpecifier() {      if (TryAltiVecVectorToken())        return true;      // Fall through. -    case tok::kw_typename: // typename T::type      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return isDeclarationSpecifier(); -    // Otherwise, not a declaration specifier. -    return false; +      return true; +    if (Tok.is(tok::identifier)) +      return false; +    return isDeclarationSpecifier(); +    case tok::coloncolon:   // ::foo::bar      if (NextToken().is(tok::kw_new) ||    // ::new          NextToken().is(tok::kw_delete))   // ::delete @@ -2117,9 +2133,8 @@ bool Parser::isDeclarationSpecifier() {      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return isDeclarationSpecifier(); -    // Otherwise, not a declaration specifier. -    return false; +      return true; +    return isDeclarationSpecifier();      // storage-class-specifier    case tok::kw_typedef: @@ -2200,7 +2215,10 @@ bool Parser::isConstructorDeclarator() {    // Parse the C++ scope specifier.    CXXScopeSpec SS; -  ParseOptionalCXXScopeSpecifier(SS, 0, true); +  if (ParseOptionalCXXScopeSpecifier(SS, 0, true)) { +    TPA.Revert(); +    return false; +  }    // Parse the constructor name.    if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { @@ -2351,7 +2369,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,        (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||         Tok.is(tok::annot_cxxscope))) {      CXXScopeSpec SS; -    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) { +    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); // ignore fail + +    if (SS.isSet()) {        if (Tok.isNot(tok::star)) {          // The scope spec really belongs to the direct-declarator.          D.getCXXScopeSpec() = SS; @@ -2507,9 +2527,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {    if (getLang().CPlusPlus && D.mayHaveIdentifier()) {      // ParseDeclaratorInternal might already have parsed the scope. -    bool afterCXXScope = D.getCXXScopeSpec().isSet() || +    bool afterCXXScope = D.getCXXScopeSpec().isSet(); +    if (!afterCXXScope) {        ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,                                       true); +      afterCXXScope = D.getCXXScopeSpec().isSet(); +    } +      if (afterCXXScope) {        if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))          // Change the declaration context for name lookup, until this function @@ -2799,7 +2823,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,    // K&R-style function:  void foo(a,b,c)    if (!getLang().CPlusPlus && Tok.is(tok::identifier)        && !TryAltiVecVectorToken()) { -    if (!TryAnnotateTypeOrScopeToken()) { +    if (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) {        // K&R identifier lists can't have typedefs as identifiers, per        // C99 6.7.5.3p11.        if (RequiresArg) { diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 225ce256b11..dbbfb9518b3 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -645,7 +645,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,      // "FOO : BAR" is not a potential typo for "FOO::BAR".      ColonProtectionRAIIObject X(*this); -    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) +    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); +    if (SS.isSet())        if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))          Diag(Tok, diag::err_expected_ident);    } @@ -1163,7 +1164,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,    // Access declarations.    if (!TemplateInfo.Kind &&        (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) && -      TryAnnotateCXXScopeToken() && +      !TryAnnotateCXXScopeToken() &&        Tok.is(tok::annot_cxxscope)) {      bool isAccessDecl = false;      if (NextToken().is(tok::identifier)) diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index f69740bf8bd..af91021d33c 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -626,6 +626,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,            Next.is(tok::l_paren)) {          // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.          if (TryAnnotateTypeOrScopeToken()) +          return ExprError(); +        if (!Tok.is(tok::identifier))            return ParseCastExpression(isUnaryExpression, isAddressOfOperand);        }      } @@ -790,7 +792,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,      if (SavedKind == tok::kw_typename) {        // postfix-expression: typename-specifier '(' expression-list[opt] ')' -      if (!TryAnnotateTypeOrScopeToken()) +      if (TryAnnotateTypeOrScopeToken())          return ExprError();      } @@ -852,6 +854,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,      // ::foo::bar -> global qualified name etc.   If TryAnnotateTypeOrScopeToken      // annotates the token, tail recurse.      if (TryAnnotateTypeOrScopeToken()) +      return ExprError(); +    if (!Tok.is(tok::coloncolon))        return ParseCastExpression(isUnaryExpression, isAddressOfOperand);      // ::new -> [C++] new-expression diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 7998b26f9bc..f1e989f4a7b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -55,7 +55,7 @@ using namespace clang;  /// member access expression, e.g., the \p T:: in \p p->T::m.  /// -/// \returns true if a scope specifier was parsed. +/// \returns true if there was an error parsing a scope specifier  bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,                                              Action::TypeTy *ObjectType,                                              bool EnteringContext, @@ -67,7 +67,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,      SS.setScopeRep(Tok.getAnnotationValue());      SS.setRange(Tok.getAnnotationRange());      ConsumeToken(); -    return true; +    return false;    }    bool HasScopeSpecifier = false; @@ -168,10 +168,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,          = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,                                               ObjectType, EnteringContext);        if (!Template) -        break; +        return true;        if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,                                    &SS, TemplateName, TemplateKWLoc, false)) -        break; +        return true;        continue;      } @@ -188,7 +188,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,          = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());        if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {          *MayBePseudoDestructor = true; -        return HasScopeSpecifier; +        return false;        }        if (TemplateId->Kind == TNK_Type_template || @@ -258,7 +258,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,            !Actions.isNonTypeNestedNameSpecifier(CurScope, SS, Tok.getLocation(),                                                  II, ObjectType)) {          *MayBePseudoDestructor = true; -        return HasScopeSpecifier; +        return false;        }        // We have an identifier followed by a '::'. Lookup this name @@ -303,7 +303,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,          ConsumeToken();          if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,                                       SourceLocation(), false)) -          break; +          return true;          continue;        }      } @@ -319,7 +319,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,    if (CheckForDestructor && Tok.is(tok::tilde))      *MayBePseudoDestructor = true; -  return HasScopeSpecifier; +  return false;  }  /// ParseCXXIdExpression - Handle id-expression. diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 6251a2f3675..516a9a620b6 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -491,7 +491,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,    while (1) {      if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) -      TryAnnotateCXXScopeToken(true); +      if (TryAnnotateCXXScopeToken(true)) +        return TPResult::Error();      if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||          (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { @@ -681,9 +682,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return isCXXDeclarationSpecifier(); -    // Otherwise, not a typename. -    return TPResult::False(); +      return TPResult::Error(); +    if (Tok.is(tok::identifier)) +      return TPResult::False(); +    return isCXXDeclarationSpecifier();    case tok::coloncolon: {    // ::foo::bar      const Token &Next = NextToken(); @@ -694,9 +696,8 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {      // Annotate typenames and C++ scope specifiers.  If we get one, just      // recurse to handle whatever we get.      if (TryAnnotateTypeOrScopeToken()) -      return isCXXDeclarationSpecifier(); -    // Otherwise, not a typename. -    return TPResult::False(); +      return TPResult::Error(); +    return isCXXDeclarationSpecifier();    }      // decl-specifier: @@ -762,7 +763,9 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {    case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed      // We've already annotated a scope; try to annotate a type. -    if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename))) +    if (TryAnnotateTypeOrScopeToken()) +      return TPResult::Error(); +    if (!Tok.is(tok::annot_typename))        return TPResult::False();      // If that succeeded, fallthrough into the generic simple-type-id case. diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 24162373e0e..a6ae9cfd0d3 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -891,8 +891,7 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {  /// specifier, and another one to get the actual type inside  /// ParseDeclarationSpecifiers).  /// -/// This returns true if the token was annotated or an unrecoverable error -/// occurs. +/// This returns true if an error occurred.  ///  /// Note that this routine emits an error if you call it with ::new or ::delete  /// as the current tokens, so only call it in contexts where these are invalid. @@ -910,11 +909,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {      //            simple-template-id      SourceLocation TypenameLoc = ConsumeToken();      CXXScopeSpec SS; -    bool HadNestedNameSpecifier -      = ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); -    if (!HadNestedNameSpecifier) { +    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false)) +      return true; +    if (!SS.isSet()) {        Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); -      return false; +      return true;      }      TypeResult Ty; @@ -928,7 +927,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {        if (TemplateId->Kind == TNK_Function_template) {          Diag(Tok, diag::err_typename_refers_to_non_type_template)            << Tok.getAnnotationRange(); -        return false; +        return true;        }        AnnotateTemplateIdTokenAsType(0); @@ -942,7 +941,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {      } else {        Diag(Tok, diag::err_expected_type_name_after_typename)          << SS.getRange(); -      return false; +      return true;      }      SourceLocation EndLoc = Tok.getLastLoc(); @@ -951,7 +950,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {      Tok.setAnnotationEndLoc(EndLoc);      Tok.setLocation(TypenameLoc);      PP.AnnotateCachedTokens(Tok); -    return true; +    return false;    }    // Remembers whether the token was originally a scope annotation. @@ -959,7 +958,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {    CXXScopeSpec SS;    if (getLang().CPlusPlus) -    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext); +    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext)) +      return true;    if (Tok.is(tok::identifier)) {      // Determine whether the identifier is a type name. @@ -976,7 +976,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {        // In case the tokens were cached, have Preprocessor replace        // them with the annotation token.        PP.AnnotateCachedTokens(Tok); -      return true; +      return false;      }      if (!getLang().CPlusPlus) { @@ -1001,7 +1001,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {            // If an unrecoverable error occurred, we need to return true here,            // because the token stream is in a damaged state.  We may not return            // a valid identifier. -          return Tok.isNot(tok::identifier); +          return true;          }        }      } @@ -1021,12 +1021,12 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {        // to produce a type annotation token. Update the template-id        // annotation token to a type annotation token now.        AnnotateTemplateIdTokenAsType(&SS); -      return true; +      return false;      }    }    if (SS.isEmpty()) -    return Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon); +    return false;    // A C++ scope specifier that isn't followed by a typename.    // Push the current token back into the token stream (or revert it if it is @@ -1044,7 +1044,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {    // just reverted back to the state we were in before being called.    if (!wasScopeAnnotation)      PP.AnnotateCachedTokens(Tok); -  return true; +  return false;  }  /// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only @@ -1061,10 +1061,10 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {           "Cannot be a type or scope token!");    CXXScopeSpec SS; -  if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext)) -    // If the token left behind is not an identifier, we either had an error or -    // successfully turned it into an annotation token. -    return Tok.isNot(tok::identifier); +  if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext)) +    return true; +  if (!SS.isSet()) +    return false;    // Push the current token back into the token stream (or revert it if it is    // cached) and use an annotation scope token for current token. @@ -1079,7 +1079,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {    // In case the tokens were cached, have Preprocessor replace them with the    // annotation token.    PP.AnnotateCachedTokens(Tok); -  return true; +  return false;  }  // Anchor the Parser::FieldCallback vtable to this translation unit.  | 

