summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-05-15 21:01:51 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-05-15 21:01:51 +0000
commita952ebbcee7bc092db0fee11b5338dca3dc589d2 (patch)
treee12fae8153ed23c1b59c64c1a8794032c7c6e2af /clang/lib/Parse/ParseDecl.cpp
parent9295df056971230934aaed55f5a5d3b65c47e952 (diff)
downloadbcm5719-llvm-a952ebbcee7bc092db0fee11b5338dca3dc589d2.tar.gz
bcm5719-llvm-a952ebbcee7bc092db0fee11b5338dca3dc589d2.zip
Don't use the implicit int rule for error recovery in C++. Instead, try to
disambiguate whether the type name was forgotten or mistyped. llvm-svn: 156854
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp59
1 files changed, 54 insertions, 5 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7ca9e280ca3..dcc96cb8614 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1638,12 +1638,13 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
// Since we know that this either implicit int (which is rare) or an
- // error, do lookahead to try to do better recovery. This never applies within
- // a type specifier.
- // FIXME: Don't bail out here in languages with no implicit int (like
- // C++ with no -fms-extensions). This is much more likely to be an undeclared
- // type or typo than a use of implicit int.
+ // error, do lookahead to try to do better recovery. This never applies
+ // within a type specifier. Outside of C++, we allow this even if the
+ // language doesn't "officially" support implicit int -- we support
+ // implicit int as an extension in C99 and C11. Allegedly, MS also
+ // supports implicit int in C++ mode.
if (DSC != DSC_type_specifier && DSC != DSC_trailing &&
+ (!getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt) &&
isValidAfterIdentifierInDeclarator(NextToken())) {
// If this token is valid for implicit int, e.g. "static x = 4", then
// we just avoid eating the identifier, so it will be parsed as the
@@ -1651,6 +1652,13 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
return false;
}
+ if (getLangOpts().CPlusPlus &&
+ 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.
+ return false;
+ }
+
// Otherwise, if we don't consume this token, we are going to emit an
// error anyway. Try to recover from various common problems. Check
// to see if this was a reference to a tag name without a tag specified.
@@ -1699,6 +1707,47 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
}
}
+ if (DSC != DSC_type_specifier && DSC != DSC_trailing) {
+ // 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
+ // x (*p)[]; // 'x' is a type
+ //
+ // Since we're in an error case (or the rare 'implicit int in C++' MS
+ // extension), we can afford to perform a tentative parse to determine
+ // which case we're in.
+ TentativeParsingAction PA(*this);
+ 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;
+ }
+
+ default:
+ // This is probably supposed to be a type. This includes cases like:
+ // int f(itn);
+ // struct S { unsinged : 4; };
+ break;
+ }
+ }
+
// This is almost certainly an invalid type name. Let the action emit a
// diagnostic and attempt to recover.
ParsedType T;
OpenPOWER on IntegriCloud