[c++1z] Enforce restriction that deduction guide is declared in the same scope as its template.
llvm-svn: 294778
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c12c9b2..2d5fd92 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8137,6 +8137,20 @@
/// 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 @@
// 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?");
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 9d9d127..dd2dfe4 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -242,6 +242,37 @@
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,