aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-13 23:27:22 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-13 23:27:22 +0000
commita786fdbf6c1d8ff08c3e61c7eb6bf2872895e2b4 (patch)
treeff286b08556defd04e78be347cdf3adfbe6425ce /lib/Parse/ParseDecl.cpp
parent15934f92c3b56aa8275d3d77d7b884088ff5d4a7 (diff)
Improve diagnostics when the parser encounters a declarator with an
unknown type name, e.g., foo::bar x; when "bar" does not refer to a type in "foo". With this change, the parser now calls into the action to perform diagnostics and can try to recover by substituting in an appropriate type. For example, this allows us to easily diagnose some missing "typename" specifiers, which we now do: test/SemaCXX/unknown-type-name.cpp:29:1: error: missing 'typename' prior to dependent type name 'A<T>::type' A<T>::type A<T>::f() { return type(); } ^~~~~~~~~~ typename Fixes PR3990. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84053 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp35
1 files changed, 29 insertions, 6 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e15a4cd688..b56c33170c 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -688,13 +688,36 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
}
}
- // Since this is almost certainly an invalid type name, emit a
- // diagnostic that says it, eat the token, and mark the declspec as
- // invalid.
- SourceRange R;
- if (SS) R = SS->getRange();
+ // This is almost certainly an invalid type name. Let the action emit a
+ // diagnostic and attempt to recover.
+ Action::TypeTy *T = 0;
+ if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc,
+ CurScope, SS, T)) {
+ // The action emitted a diagnostic, so we don't have to.
+ if (T) {
+ // The action has suggested that the type T could be used. Set that as
+ // the type in the declaration specifiers, consume the would-be type
+ // name token, and we're done.
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
+ false);
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+
+ // There may be other declaration specifiers after this.
+ return true;
+ }
+
+ // Fall through; the action had no suggestion for us.
+ } else {
+ // The action did not emit a diagnostic, so emit one now.
+ SourceRange R;
+ if (SS) R = SS->getRange();
+ Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+ }
- Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+ // Mark this as an error.
const char *PrevSpec;
unsigned DiagID;
DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID);