r294778 - [c++1z] Enforce restriction that deduction guide is declared in the same scope as its template.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 10 12:39:59 PST 2017
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() {
More information about the cfe-commits
mailing list