forked from OSchip/llvm-project
PR37631: verify that a member deduction guide has the same access as its template.
llvm-svn: 333599
This commit is contained in:
parent
e863297775
commit
e4899c1648
|
@ -2115,9 +2115,16 @@ def err_deduction_guide_explicit_mismatch : Error<
|
|||
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
|
||||
"%select{explicitly instantiated|explicitly specialized}0">;
|
||||
def err_deduction_guide_template_not_deducible : Error<
|
||||
"deduction guide template contains "
|
||||
"%select{a template parameter|template parameters}0 that cannot be "
|
||||
"deduced">;
|
||||
"deduction guide template contains "
|
||||
"%select{a template parameter|template parameters}0 that cannot be "
|
||||
"deduced">;
|
||||
def err_deduction_guide_wrong_access : Error<
|
||||
"deduction guide has different access from the corresponding "
|
||||
"member template">;
|
||||
def note_deduction_guide_template_access : Note<
|
||||
"member template declared %0 here">;
|
||||
def note_deduction_guide_access : Note<
|
||||
"deduction guide declared %0 by intervening access specifier">;
|
||||
|
||||
// C++1y deduced return types
|
||||
def err_auto_fn_deduction_failure : Error<
|
||||
|
|
|
@ -3103,14 +3103,38 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
Member->setInvalidDecl();
|
||||
}
|
||||
|
||||
NamedDecl *NonTemplateMember = Member;
|
||||
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
|
||||
NonTemplateMember = FunTmpl->getTemplatedDecl();
|
||||
else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
|
||||
NonTemplateMember = VarTmpl->getTemplatedDecl();
|
||||
|
||||
Member->setAccess(AS);
|
||||
|
||||
// If we have declared a member function template or static data member
|
||||
// template, set the access of the templated declaration as well.
|
||||
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
|
||||
FunTmpl->getTemplatedDecl()->setAccess(AS);
|
||||
else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
|
||||
VarTmpl->getTemplatedDecl()->setAccess(AS);
|
||||
if (NonTemplateMember != Member)
|
||||
NonTemplateMember->setAccess(AS);
|
||||
|
||||
// C++ [temp.deduct.guide]p3:
|
||||
// A deduction guide [...] for a member class template [shall be
|
||||
// declared] with the same access [as the template].
|
||||
if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) {
|
||||
auto *TD = DG->getDeducedTemplate();
|
||||
if (AS != TD->getAccess()) {
|
||||
Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access);
|
||||
Diag(TD->getLocStart(), diag::note_deduction_guide_template_access)
|
||||
<< TD->getAccess();
|
||||
const AccessSpecDecl *LastAccessSpec = nullptr;
|
||||
for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) {
|
||||
if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D))
|
||||
LastAccessSpec = AccessSpec;
|
||||
}
|
||||
assert(LastAccessSpec && "differing access with no access specifier");
|
||||
Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access)
|
||||
<< AS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (VS.isOverrideSpecified())
|
||||
|
|
|
@ -330,6 +330,22 @@ namespace member_guides {
|
|||
Bar(int) -> Bar<int>;
|
||||
};
|
||||
Foo<int>::Bar b = 0;
|
||||
|
||||
struct A {
|
||||
template<typename T> struct Public; // expected-note {{declared public}}
|
||||
Public(float) -> Public<float>;
|
||||
protected: // expected-note {{declared protected by intervening access specifier}}
|
||||
template<typename T> struct Protected; // expected-note 2{{declared protected}}
|
||||
Protected(float) -> Protected<float>;
|
||||
Public(int) -> Public<int>; // expected-error {{different access}}
|
||||
private: // expected-note {{declared private by intervening access specifier}}
|
||||
template<typename T> struct Private; // expected-note {{declared private}}
|
||||
Protected(int) -> Protected<int>; // expected-error {{different access}}
|
||||
public: // expected-note 2{{declared public by intervening access specifier}}
|
||||
template<typename T> Public(T) -> Public<T>;
|
||||
template<typename T> Protected(T) -> Protected<T>; // expected-error {{different access}}
|
||||
template<typename T> Private(T) -> Private<T>; // expected-error {{different access}}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
Loading…
Reference in New Issue