diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 31 |
4 files changed, 67 insertions, 7 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index e15a4cd6880..b56c33170cb 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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); 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 |

