diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-05-30 22:13:43 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-05-30 22:13:43 +0000 |
commit | e4899c16480dfb06a0265274d0b5b0fe3b370b8a (patch) | |
tree | 580366c742dff5d37cd53a967a33b0e9aeaa7562 | |
parent | e86329777563a372881a3952b2f73dc90becec6e (diff) | |
download | bcm5719-llvm-e4899c16480dfb06a0265274d0b5b0fe3b370b8a.tar.gz bcm5719-llvm-e4899c16480dfb06a0265274d0b5b0fe3b370b8a.zip |
PR37631: verify that a member deduction guide has the same access as its template.
llvm-svn: 333599
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 32 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp | 16 |
3 files changed, 54 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b4d76ba9183..16836b98614 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d5af147279a..8dbf5e7ac14 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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()) diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index 90f168d3fcc..de61e44a6e9 100644 --- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -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 |