From d95450421ee3b7cebfb18ce1312310d6c703431c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 9 Dec 2010 00:06:27 +0000 Subject: [PATCH] A typename specifier can end up referring to a unresolved using declaration that is a value in ill-formed code. Instead of crashing, treat this as a dependent typename specifier and suggest that the using add "typename" into the using declaration. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121322 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 5 +++++ lib/Sema/SemaTemplate.cpp | 19 ++++++++++++++++++- test/SemaTemplate/typename-specifier-4.cpp | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 01e7962ac6..55270b0116 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1782,6 +1782,11 @@ def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; def ext_typename_outside_of_template : ExtWarn< "'typename' occurs outside of a template">, InGroup; +def err_typename_refers_to_using_value_decl : Error< + "typename specifier refers to a dependent using declaration for a value " + "%0 in %1">; +def note_using_value_decl_missing_typename : Note< + "add 'typename' to treat this using declaration as a type">; def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 29f77f333d..5d3b75ede4 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5699,6 +5699,23 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, case LookupResult::NotFound: DiagID = diag::err_typename_nested_not_found; break; + + case LookupResult::FoundUnresolvedValue: { + // We found a using declaration that is a value. Most likely, the using + // declaration itself is meant to have the 'typename' keyword. + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(), + IILoc); + Diag(IILoc, diag::err_typename_refers_to_using_value_decl) + << Name << Ctx << FullRange; + if (UnresolvedUsingValueDecl *Using + = dyn_cast(Result.getRepresentativeDecl())){ + SourceLocation Loc = Using->getTargetNestedNameRange().getBegin(); + Diag(Loc, diag::note_using_value_decl_missing_typename) + << FixItHint::CreateInsertion(Loc, "typename "); + } + } + // Fall through to create a dependent typename type, from which we can recover + // better. case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. @@ -5716,7 +5733,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, Referenced = Result.getFoundDecl(); break; - case LookupResult::FoundUnresolvedValue: + llvm_unreachable("unresolved using decl in non-dependent context"); return QualType(); diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp index f5bc7477dd..38045e0a31 100644 --- a/test/SemaTemplate/typename-specifier-4.cpp +++ b/test/SemaTemplate/typename-specifier-4.cpp @@ -134,3 +134,23 @@ namespace PR7419 { template typename T::Y::Z::W *S::f() { } template typename T::template Y::template Z::template W S::g() { } } + +namespace rdar8740998 { + template + struct X : public T { + using T::iterator; // expected-note{{add 'typename' to treat this using declaration as a type}} \ + // expected-error{{dependent using declaration resolved to type without 'typename'}} + + void f() { + typename X::iterator i; // expected-error{{typename specifier refers to a dependent using declaration for a value 'iterator' in 'X'}} + } + }; + + struct HasIterator { + typedef int *iterator; // expected-note{{target of using declaration}} + }; + + void test_X(X xi) { // expected-note{{in instantiation of template class}} + xi.f(); + } +} -- 2.40.0