зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
b76c2322bf
Коммит
c8e27cc402
|
@ -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'}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче