diff options
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 18 | ||||
-rw-r--r-- | test/SemaCXX/access.cpp | 76 |
2 files changed, 84 insertions, 10 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 79a9d3c9fd..3ef1fdebaa 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -84,10 +84,10 @@ struct EffectiveContext { : Inner(DC), Dependent(DC->isDependentContext()) { - // C++ [class.access.nest]p1: + // C++11 [class.access.nest]p1: // A nested class is a member and as such has the same access // rights as any other member. - // C++ [class.access]p2: + // C++11 [class.access]p2: // A member of a class can also access all the names to which // the class has access. A local class of a member function // may access the same names that the member function itself @@ -1476,18 +1476,18 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, llvm_unreachable("falling off end"); } -void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) { +void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { // Access control for names used in the declarations of functions // and function templates should normally be evaluated in the context // of the declaration, just in case it's a friend of something. // However, this does not apply to local extern declarations. - DeclContext *DC = decl->getDeclContext(); - if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { - if (!DC->isFunctionOrMethod()) DC = fn; - } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) { - // Never a local declaration. - DC = fnt->getTemplatedDecl(); + DeclContext *DC = D->getDeclContext(); + if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { + if (!DC->isFunctionOrMethod()) + DC = FN; + } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { + DC = cast<DeclContext>(TD->getTemplatedDecl()); } EffectiveContext EC(DC); diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index 18ad301b5f..50f2eff87b 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s class C { struct S; // expected-note {{previously declared 'private' here}} @@ -32,3 +32,77 @@ namespace test1 { class X {}; }; } + +// PR15209 +namespace PR15209 { + namespace alias_templates { + template<typename T1, typename T2> struct U { }; + template<typename T1> using W = U<T1, float>; + + class A { + typedef int I; + static constexpr I x = 0; // expected-note {{implicitly declared private here}} + static constexpr I y = 42; // expected-note {{implicitly declared private here}} + friend W<int>; + }; + + template<typename T1> + struct U<T1, float> { + int v_; + // the following will trigger for U<float, float> instantiation, via W<float> + U() : v_(A::x) { } // expected-error {{'x' is a private member of 'PR15209::alias_templates::A'}} + }; + + template<typename T1> + struct U<T1, int> { + int v_; + U() : v_(A::y) { } // expected-error {{'y' is a private member of 'PR15209::alias_templates::A'}} + }; + + template struct U<int, int>; // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<int, int>::U' requested here}} + + void f() + { + W<int>(); + // we should issue diagnostics for the following + W<float>(); // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<float, float>::U' requested here}} + } + } + + namespace templates { + class A { + typedef int I; // expected-note {{implicitly declared private here}} + static constexpr I x = 0; // expected-note {{implicitly declared private here}} + + template<int> friend struct B; + template<int> struct C; + template<template<int> class T> friend struct TT; + template<typename T> friend void funct(T); + }; + template<A::I> struct B { }; + + template<A::I> struct A::C { }; + + template<template<A::I> class T> struct TT { + T<A::x> t; + }; + + template struct TT<B>; + template<A::I> struct D { }; // expected-error {{'I' is a private member of 'PR15209::templates::A'}} + template struct TT<D>; + + // function template case + template<typename T> + void funct(T) + { + (void)A::x; + } + + template void funct<int>(int); + + void f() + { + (void)A::x; // expected-error {{'x' is a private member of 'PR15209::templates::A'}} + } + } +} |