summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
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
commit15e5602e599856f80a3b77b7c05715971ec339b8 (patch)
tree31ccce478610aeeaff7ca3af816bdbcf39defb3e /clang/lib/Sema
parentf258caa7182e0714e5c097ebbf3375ac7d4611bd (diff)
downloadbcm5719-llvm-15e5602e599856f80a3b77b7c05715971ec339b8.tar.gz
bcm5719-llvm-15e5602e599856f80a3b77b7c05715971ec339b8.zip
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. llvm-svn: 84053
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.cpp1
-rw-r--r--clang/lib/Sema/Sema.h7
-rw-r--r--clang/lib/Sema/SemaDecl.cpp31
3 files changed, 38 insertions, 1 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index c289abfea86..ba05a07f265 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -117,6 +117,7 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
llvm::raw_string_ostream OS(S);
reinterpret_cast<NestedNameSpecifier*> (Val)->print(OS,
Context.PrintingPolicy);
+ NeedQuotes = false;
} else {
assert(Kind == Diagnostic::ak_declcontext);
DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 465eca70ed3..04addfd3a98 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -523,7 +523,12 @@ public:
Scope *S, const CXXScopeSpec *SS,
bool isClassName = false);
virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S);
-
+ virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TypeTy *&SuggestedType);
+
virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9f03cb284ca..606b33f5f74 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -199,6 +200,36 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
return DeclSpec::TST_unspecified;
}
+bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TypeTy *&SuggestedType) {
+ // We don't have anything to suggest (yet).
+ SuggestedType = 0;
+
+ // FIXME: Should we move the logic that tries to recover from a missing tag
+ // (struct, union, enum) from Parser::ParseImplicitInt here, instead?
+
+ if (!SS)
+ Diag(IILoc, diag::err_unknown_typename) << &II;
+ else if (DeclContext *DC = computeDeclContext(*SS, false))
+ Diag(IILoc, diag::err_typename_nested_not_found)
+ << &II << DC << SS->getRange();
+ else if (isDependentScopeSpecifier(*SS)) {
+ Diag(SS->getRange().getBegin(), diag::err_typename_missing)
+ << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
+ << SourceRange(SS->getRange().getBegin(), IILoc)
+ << CodeModificationHint::CreateInsertion(SS->getRange().getBegin(),
+ "typename ");
+ SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get();
+ } else {
+ assert(SS && SS->isInvalid() &&
+ "Invalid scope specifier has already been diagnosed");
+ }
+
+ return true;
+}
// Determines the context to return to after temporarily entering a
// context. This depends in an unnecessarily complicated way on the
OpenPOWER on IntegriCloud