Author: rsmith Date: Fri Feb 10 14:39:58 2017 New Revision: 294778 URL: http://llvm.org/viewvc/llvm-project?rev=294778&view=rev Log: [c++1z] Enforce restriction that deduction guide is declared in the same scope as its template.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=294778&r1=294777&r2=294778&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 10 14:39:58 2017 @@ -1993,6 +1993,8 @@ def err_deduction_guide_name_not_class_t "cannot specify deduction guide for " "%select{<error>|function template|variable template|alias template|" "template template parameter|dependent template name}0 %1">; +def err_deduction_guide_wrong_scope : Error< + "deduction guide must be declared in the same scope as template %q0">; def err_deduction_guide_defines_function : Error< "deduction guide cannot have a function definition">; def err_deduction_guide_explicit_mismatch : Error< Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=294778&r1=294777&r2=294778&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb 10 14:39:58 2017 @@ -5831,17 +5831,7 @@ public: /// deduction-guide declaration. bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name, SourceLocation NameLoc, - ParsedTemplateTy *Template = nullptr) { - CXXScopeSpec SS; - UnqualifiedId Id; - Id.setIdentifier(&Name, NameLoc); - TemplateTy TemplateFallback; - bool MemberOfUnknownSpecialization; - // FIXME: Use redeclaration lookup! - return isTemplateName(S, SS, false, Id, ParsedType(), false, - Template ? *Template : TemplateFallback, - MemberOfUnknownSpecialization) == TNK_Type_template; - } + ParsedTemplateTy *Template = nullptr); bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, SourceLocation IILoc, Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=294778&r1=294777&r2=294778&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb 10 14:39:58 2017 @@ -8137,6 +8137,20 @@ struct BadSpecifierDiagnoser { /// grammar. void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, StorageClass &SC) { + TemplateName GuidedTemplate = D.getName().TemplateName.get().get(); + TemplateDecl *GuidedTemplateDecl = GuidedTemplate.getAsTemplateDecl(); + assert(GuidedTemplateDecl && "missing template decl for deduction guide"); + + // C++ [temp.deduct.guide]p3: + // A deduction-gide shall be declared in the same scope as the + // corresponding class template. + if (!CurContext->getRedeclContext()->Equals( + GuidedTemplateDecl->getDeclContext()->getRedeclContext())) { + Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope) + << GuidedTemplateDecl; + Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here); + } + auto &DS = D.getMutableDeclSpec(); // We leave 'friend' and 'virtual' to be rejected in the normal way. if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() || @@ -8196,7 +8210,6 @@ void Sema::CheckDeductionGuideDeclarator // Check that the return type is written as a specialization of // the template specified as the deduction-guide's name. ParsedType TrailingReturnType = Chunk.Fun.getTrailingReturnType(); - TemplateName GuidedTemplate = D.getName().TemplateName.get().get(); TypeSourceInfo *TSI = nullptr; QualType RetTy = GetTypeFromParser(TrailingReturnType, &TSI); assert(TSI && "deduction guide has valid type but invalid return type?"); Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=294778&r1=294777&r2=294778&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb 10 14:39:58 2017 @@ -242,6 +242,37 @@ TemplateNameKind Sema::isTemplateName(Sc return TemplateKind; } +bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name, + SourceLocation NameLoc, + ParsedTemplateTy *Template) { + CXXScopeSpec SS; + bool MemberOfUnknownSpecialization = false; + + // We could use redeclaration lookup here, but we don't need to: the + // syntactic form of a deduction guide is enough to identify it even + // if we can't look up the template name at all. + LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName); + LookupTemplateName(R, S, SS, /*ObjectType*/QualType(), + /*EnteringContext*/false, MemberOfUnknownSpecialization); + + if (R.empty()) return false; + if (R.isAmbiguous()) { + // FIXME: Diagnose an ambiguity if we find at least one template. + R.suppressDiagnostics(); + return false; + } + + // We only treat template-names that name type templates as valid deduction + // guide names. + TemplateDecl *TD = R.getAsSingle<TemplateDecl>(); + if (!TD || !getAsTypeTemplateDecl(TD)) + return false; + + if (Template) + *Template = TemplateTy::make(TemplateName(TD)); + return true; +} + bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, Modified: cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp?rev=294778&r1=294777&r2=294778&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp Fri Feb 10 14:39:58 2017 @@ -40,28 +40,28 @@ template<typename T> A(T*) -> const A<T> // class template. namespace WrongScope { namespace { - template<typename T> struct AnonNS1 {}; + template<typename T> struct AnonNS1 {}; // expected-note {{here}} AnonNS1(float) -> AnonNS1<float>; // ok } - AnonNS1(int) -> AnonNS1<int>; // FIXME - template<typename T> struct AnonNS2 {}; + AnonNS1(int) -> AnonNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::}} + template<typename T> struct AnonNS2 {}; // expected-note {{here}} namespace { AnonNS1(char) -> AnonNS1<char>; // ok - AnonNS2(int) -> AnonNS2<int>; // FIXME + AnonNS2(int) -> AnonNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::AnonNS2'}} } namespace N { - template<typename T> struct NamedNS1 {}; - template<typename T> struct NamedNS2 {}; + template<typename T> struct NamedNS1 {}; // expected-note {{here}} + template<typename T> struct NamedNS2 {}; // expected-note {{here}} } using N::NamedNS1; - NamedNS1(int) -> NamedNS1<int>; // FIXME + NamedNS1(int) -> NamedNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template}} using namespace N; - NamedNS2(int) -> NamedNS2<int>; // FIXME + NamedNS2(int) -> NamedNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template}} struct ClassMemberA { - template<typename T> struct X {}; + template<typename T> struct X {}; // expected-note {{here}} }; struct ClassMemberB : ClassMemberA { - X(int) -> X<int>; // FIXME + X(int) -> X<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::ClassMemberA::X'}} }; template<typename T> struct Local {}; void f() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits