mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-30 00:56:06 +00:00
Implement DR580: access checks for template parameters of a class template are
performed within the context of that class template. Patch by Ismail Pazarbasi! llvm-svn: 180707
This commit is contained in:
parent
7cd81c55c7
commit
ad5c1ca44d
@ -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);
|
||||
|
@ -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'}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user