forked from OSchip/llvm-project
When a type-id is unexpectedly given a name, assume that the name is unrelated
syntax unless we have a reason to think otherwise. This improves error recovery in a couple of cases. llvm-svn: 303398
This commit is contained in:
parent
8f1d87a79a
commit
74639b1900
|
@ -1999,41 +1999,6 @@ public:
|
||||||
llvm_unreachable("unknown context kind!");
|
llvm_unreachable("unknown context kind!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// diagnoseIdentifier - Return true if the identifier is prohibited and
|
|
||||||
/// should be diagnosed (because it cannot be anything else).
|
|
||||||
bool diagnoseIdentifier() const {
|
|
||||||
switch (Context) {
|
|
||||||
case FileContext:
|
|
||||||
case KNRTypeListContext:
|
|
||||||
case MemberContext:
|
|
||||||
case BlockContext:
|
|
||||||
case ForContext:
|
|
||||||
case InitStmtContext:
|
|
||||||
case ConditionContext:
|
|
||||||
case PrototypeContext:
|
|
||||||
case LambdaExprParameterContext:
|
|
||||||
case TemplateParamContext:
|
|
||||||
case CXXCatchContext:
|
|
||||||
case ObjCCatchContext:
|
|
||||||
case TypeNameContext:
|
|
||||||
case FunctionalCastContext:
|
|
||||||
case ConversionIdContext:
|
|
||||||
case ObjCParameterContext:
|
|
||||||
case ObjCResultContext:
|
|
||||||
case BlockLiteralContext:
|
|
||||||
case CXXNewContext:
|
|
||||||
case LambdaExprContext:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case AliasDeclContext:
|
|
||||||
case AliasTemplateContext:
|
|
||||||
case TemplateTypeArgContext:
|
|
||||||
case TrailingReturnContext:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
llvm_unreachable("unknown context kind!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true if the context permits a C++17 decomposition declarator.
|
/// Return true if the context permits a C++17 decomposition declarator.
|
||||||
bool mayHaveDecompositionDeclarator() const {
|
bool mayHaveDecompositionDeclarator() const {
|
||||||
switch (Context) {
|
switch (Context) {
|
||||||
|
|
|
@ -5542,11 +5542,28 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||||
D.SetRangeEnd(Tok.getLocation());
|
D.SetRangeEnd(Tok.getLocation());
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
goto PastIdentifier;
|
goto PastIdentifier;
|
||||||
} else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) {
|
} else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) {
|
||||||
// A virt-specifier isn't treated as an identifier if it appears after a
|
// We're not allowed an identifier here, but we got one. Try to figure out
|
||||||
// trailing-return-type.
|
// if the user was trying to attach a name to the type, or whether the name
|
||||||
if (D.getContext() != Declarator::TrailingReturnContext ||
|
// is some unrelated trailing syntax.
|
||||||
!isCXX11VirtSpecifier(Tok)) {
|
bool DiagnoseIdentifier = false;
|
||||||
|
if (D.hasGroupingParens())
|
||||||
|
// An identifier within parens is unlikely to be intended to be anything
|
||||||
|
// other than a name being "declared".
|
||||||
|
DiagnoseIdentifier = true;
|
||||||
|
else if (D.getContext() == Declarator::TemplateTypeArgContext)
|
||||||
|
// T<int N> is an accidental identifier; T<int N indicates a missing '>'.
|
||||||
|
DiagnoseIdentifier =
|
||||||
|
NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
|
||||||
|
else if (D.getContext() == Declarator::AliasDeclContext ||
|
||||||
|
D.getContext() == Declarator::AliasTemplateContext)
|
||||||
|
// The most likely error is that the ';' was forgotten.
|
||||||
|
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
|
||||||
|
else if (D.getContext() == Declarator::TrailingReturnContext &&
|
||||||
|
!isCXX11VirtSpecifier(Tok))
|
||||||
|
DiagnoseIdentifier = NextToken().isOneOf(
|
||||||
|
tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
|
||||||
|
if (DiagnoseIdentifier) {
|
||||||
Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
|
Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
|
||||||
<< FixItHint::CreateRemoval(Tok.getLocation());
|
<< FixItHint::CreateRemoval(Tok.getLocation());
|
||||||
D.SetIdentifier(nullptr, Tok.getLocation());
|
D.SetIdentifier(nullptr, Tok.getLocation());
|
||||||
|
|
|
@ -10,7 +10,7 @@ template<typename T> struct A {};
|
||||||
// Check for template argument lists followed by junk
|
// Check for template argument lists followed by junk
|
||||||
// FIXME: The diagnostics here aren't great...
|
// FIXME: The diagnostics here aren't great...
|
||||||
A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}}
|
A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}}
|
||||||
A<int x; // expected-error {{type-id cannot have a name}} expected-error {{expected '>'}}
|
A<int x; // expected-error {{expected '>'}}
|
||||||
|
|
||||||
// PR8912
|
// PR8912
|
||||||
template <bool> struct S {};
|
template <bool> struct S {};
|
||||||
|
|
|
@ -137,6 +137,9 @@ namespace AliasDeclEndLocation {
|
||||||
>\
|
>\
|
||||||
> // expected-error {{expected ';' after alias declaration}}
|
> // expected-error {{expected ';' after alias declaration}}
|
||||||
;
|
;
|
||||||
|
using D = AliasDeclEndLocation::A<int
|
||||||
|
> // expected-error {{expected ';' after alias declaration}}
|
||||||
|
B something_else;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Base { virtual void f() = 0; virtual void g() = 0; virtual void h() = 0; };
|
struct Base { virtual void f() = 0; virtual void g() = 0; virtual void h() = 0; };
|
||||||
|
|
|
@ -37,7 +37,7 @@ void f0() {
|
||||||
|
|
||||||
// rdar://problem/8962770
|
// rdar://problem/8962770
|
||||||
void test4() {
|
void test4() {
|
||||||
int (^f)() = ^((x)) { }; // expected-error {{expected ')'}} expected-warning {{type specifier missing}} expected-note {{to match this}}
|
int (^f)() = ^((x)) { }; // expected-warning {{type specifier missing}} expected-error {{type-id cannot have a name}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rdar://problem/9170609
|
// rdar://problem/9170609
|
||||||
|
|
Loading…
Reference in New Issue