forked from OSchip/llvm-project
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
This commit is contained in:
parent
663f658d87
commit
1f476a1783
|
@ -320,9 +320,9 @@ private:
|
|||
/// This returns true if the token was annotated.
|
||||
bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false);
|
||||
|
||||
/// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but only
|
||||
/// annotates C++ scope specifiers. This returns true if the token was
|
||||
/// annotated.
|
||||
/// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but
|
||||
/// only annotates C++ scope specifiers. This returns true if there
|
||||
/// was an unrecoverable error.
|
||||
bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
|
||||
|
||||
/// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -33,5 +33,4 @@ template <typename T> void g(T);
|
|||
template <typename T> void g(T, T);
|
||||
|
||||
int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \
|
||||
// expected-error{{cannot determine the type of an overloaded function}} \
|
||||
// FIXME: expected-error{{use of undeclared identifier}}
|
||||
// expected-error{{cannot determine the type of an overloaded function}}
|
||||
|
|
|
@ -5,5 +5,5 @@ template<typename T> struct A {};
|
|||
// Check for template argument lists followed by junk
|
||||
// FIXME: The diagnostics here aren't great...
|
||||
A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}}
|
||||
A<int x; // expected-error {{expected '>'}} expected-error {{C++ requires a type specifier for all declarations}}
|
||||
A<int x; // expected-error {{expected '>'}}
|
||||
|
||||
|
|
|
@ -12,8 +12,7 @@ int A::*pdi1;
|
|||
int (::A::*pdi2);
|
||||
int (A::*pfi)(int);
|
||||
|
||||
int B::*pbi; // expected-error {{expected a class or namespace}} \
|
||||
// expected-error{{does not point into a class}}
|
||||
int B::*pbi; // expected-error {{expected a class or namespace}}
|
||||
int C::*pci; // expected-error {{'pci' does not point into a class}}
|
||||
void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
|
||||
int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}}
|
||||
|
|
|
@ -13,8 +13,9 @@ namespace A {
|
|||
}
|
||||
|
||||
A:: ; // expected-error {{expected unqualified-id}}
|
||||
::A::ax::undef ex3; // expected-error {{no member named}}
|
||||
A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}}
|
||||
// FIXME: redundant errors
|
||||
::A::ax::undef ex3; // expected-error {{no member named}} expected-error {{unknown type name}}
|
||||
A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{unknown type name}}
|
||||
|
||||
int A::C::Ag1() { return 0; }
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ namespace PR6031 {
|
|||
int foo() {
|
||||
class NoDepBase::Nested nested; // expected-error{{'Nested' does not name a tag member in the specified scope}}
|
||||
typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \
|
||||
// FIXME: expected-error{{expected an identifier or template-id after '::'}} \
|
||||
// FIXME: expected-error{{unqualified-id}}
|
||||
return NoDepBase::a; // expected-error{{no member named 'a' in 'struct PR6031::NoDepBase'}}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace PR6161 {
|
|||
// expected-error{{expected class name}} \
|
||||
// expected-note{{attempt to specialize declaration here}}
|
||||
{
|
||||
static locale::id id; // expected-error{{use of undeclared identifier}}
|
||||
static locale::id id; // expected-error{{use of undeclared identifier}} FIXME: expected-error {{unknown type name}}
|
||||
};
|
||||
numpunct<char>::~numpunct(); // expected-error{{template specialization requires 'template<>'}} \
|
||||
// expected-error{{specialization of member 'PR6161::numpunct<char>::~numpunct' does not specialize an instantiated member}}
|
||||
|
|
|
@ -49,6 +49,5 @@ struct ::N::A<int>::X {
|
|||
template<typename T>
|
||||
struct TestA {
|
||||
typedef typename N::template B<T>::type type; // expected-error{{'B' following the 'template' keyword does not refer to a template}} \
|
||||
// expected-error{{identifier or template-id}} \
|
||||
// expected-error{{expected member name}}
|
||||
};
|
||||
|
|
|
@ -10,3 +10,10 @@ A<int, 0, X> * a1;
|
|||
|
||||
A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}}
|
||||
A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}}
|
||||
|
||||
namespace test0 {
|
||||
template <class t> class foo {};
|
||||
template <class t> class bar {
|
||||
bar(::test0::foo<tee> *ptr) {} // FIXME(redundant): expected-error 2 {{use of undeclared identifier 'tee'}}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue