PR17567: Improve diagnostic for a mistyped constructor name. If we see something
that looks like a function declaration, except that it's missing a return type,
try typo-correcting it to the relevant constructor name.
In passing, fix a bug where the missing-type-specifier recovery codepath would
drop a preceding scope specifier on the floor, leading to follow-on diagnostics
and incorrect recovery for the auto-in-c++98 hack.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192644 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 31349ce..0f480c1 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2095,6 +2095,8 @@
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
// Don't require a type specifier if we have the 'auto' storage class
// specifier in C++98 -- we'll promote it to a type specifier.
+ if (SS)
+ AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
return false;
}
@@ -2156,16 +2158,6 @@
// Look ahead to the next token to try to figure out what this declaration
// was supposed to be.
switch (NextToken().getKind()) {
- case tok::comma:
- case tok::equal:
- case tok::kw_asm:
- case tok::l_brace:
- case tok::l_square:
- case tok::semi:
- // This looks like a variable declaration. The type is probably missing.
- // We're done parsing decl-specifiers.
- return false;
-
case tok::l_paren: {
// static x(4); // 'x' is not a type
// x(int n); // 'x' is not a type
@@ -2178,12 +2170,37 @@
ConsumeToken();
TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
PA.Revert();
- if (TPR == TPResult::False())
- return false;
- // The identifier is followed by a parenthesized declarator.
- // It's supposed to be a type.
- break;
+
+ if (TPR != TPResult::False()) {
+ // The identifier is followed by a parenthesized declarator.
+ // It's supposed to be a type.
+ break;
+ }
+
+ // If we're in a context where we could be declaring a constructor,
+ // check whether this is a constructor declaration with a bogus name.
+ if (DSC == DSC_class || (DSC == DSC_top_level && SS)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (Actions.isCurrentClassNameTypo(II, SS)) {
+ Diag(Loc, diag::err_constructor_bad_name)
+ << Tok.getIdentifierInfo() << II
+ << FixItHint::CreateReplacement(Tok.getLocation(), II->getName());
+ Tok.setIdentifierInfo(II);
+ }
+ }
+ // Fall through.
}
+ case tok::comma:
+ case tok::equal:
+ case tok::kw_asm:
+ case tok::l_brace:
+ case tok::l_square:
+ case tok::semi:
+ // This looks like a variable or function declaration. The type is
+ // probably missing. We're done parsing decl-specifiers.
+ if (SS)
+ AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
+ return false;
default:
// This is probably supposed to be a type. This includes cases like: