fix PR4452, a crash on invalid. The error recovery is still terrible in this case

but at least we don't crash :)


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74264 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-06-26 04:27:47 +00:00
Родитель b76c2322bf
Коммит c8e27cc402
5 изменённых файлов: 63 добавлений и 13 удалений

Просмотреть файл

@ -1193,7 +1193,7 @@ private:
TemplateArgLocationList &TemplateArgLocations,
SourceLocation &RAngleLoc);
void AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
SourceLocation TemplateKWLoc = SourceLocation(),
bool AllowTypeAnnotation = true);

Просмотреть файл

@ -85,8 +85,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
= Actions.ActOnDependentTemplateName(TemplateKWLoc,
*Tok.getIdentifierInfo(),
Tok.getLocation(), SS);
AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
&SS, TemplateKWLoc, false);
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
&SS, TemplateKWLoc, false))
break;
continue;
}
@ -179,7 +181,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
// because some clients (e.g., the parsing of class template
// specializations) still want to see the original template-id
// token.
AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), false);
if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(),
false))
break;
continue;
}
}

Просмотреть файл

@ -621,7 +621,11 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
/// replaced with a type annotation token. Otherwise, the
/// simple-template-id is always replaced with a template-id
/// annotation token.
void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
///
/// If an unrecoverable parse error occurs and no annotation token can be
/// formed, this function returns true.
///
bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
SourceLocation TemplateKWLoc,
bool AllowTypeAnnotation) {
@ -644,14 +648,19 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateArgIsType,
TemplateArgLocations,
RAngleLoc);
if (Invalid) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
if (Tok.is(tok::greater))
ConsumeToken();
return true;
}
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
TemplateArgIsType.data(),
TemplateArgs.size());
if (Invalid) // FIXME: How to recover from a broken template-id?
return;
// Build the annotation token.
if (TNK == TNK_Type_template && AllowTypeAnnotation) {
Action::TypeResult Type
@ -659,8 +668,13 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
LAngleLoc, TemplateArgsPtr,
&TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid()) // FIXME: better recovery?
return;
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
if (Tok.is(tok::greater))
ConsumeToken();
return true;
}
Tok.setKind(tok::annot_typename);
Tok.setAnnotationValue(Type.get());
@ -705,6 +719,7 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// In case the tokens were cached, have Preprocessor replace them with the
// annotation token.
PP.AnnotateCachedTokens(Tok);
return false;
}
/// \brief Replaces a template-id annotation token with a type

Просмотреть файл

@ -839,7 +839,8 @@ 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.
/// This returns true if the token was annotated or an unrecoverable error
/// occurs.
///
/// 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.
@ -934,7 +935,12 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
if (TemplateNameKind TNK
= Actions.isTemplateName(*Tok.getIdentifierInfo(),
CurScope, Template, &SS))
AnnotateTemplateIdToken(Template, TNK, &SS);
if (AnnotateTemplateIdToken(Template, TNK, &SS)) {
// 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);
}
}
// The current token, which is either an identifier or a
@ -978,7 +984,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
/// annotates C++ scope specifiers and template-ids. This returns
/// true if the token was annotated.
/// true if the token was annotated or there was an error that could not be
/// recovered from.
///
/// 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.

Просмотреть файл

@ -171,3 +171,27 @@ Y::foo y; // expected-error{{incomplete type 'struct Y' named in nested name spe
X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \
// expected-error{{C++ requires a type specifier for all declarations}} \
// expected-error{{only constructors take base initializers}}
namespace somens {
struct a { };
}
template <typename T>
class foo {
};
// PR4452
// FIXME: This error recovery sucks.
foo<somens:a> a2; // expected-error {{unexpected namespace name 'somens': expected expression}} \
expected-error {{C++ requires a type specifier for all declarations}}
// FIXME: This is bogus, there is no int here!
somens::a a3 = a2; // expected-error {{cannot initialize 'a3' with an lvalue of type 'int'}}