forked from OSchip/llvm-project
248 lines
8.7 KiB
C++
248 lines
8.7 KiB
C++
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
|
|
|
|
// C++20 [temp.spec] 13.9/6:
|
|
// The usual access checking rules do not apply to names in a declaration
|
|
// of an explicit instantiation or explicit specialization, with the
|
|
// exception of names appearing in a function body, default argument,
|
|
// base-clause, member-specification, enumerator-list, or static data member
|
|
// or variable template initializer.
|
|
// [Note : In particular, the template arguments and names used in the
|
|
// function declarator(including parameter types, return types and exception
|
|
// specifications) may be private types or objects that would normally not be
|
|
// accessible. — end note]
|
|
|
|
class A {
|
|
// expected-note@+1 17{{implicitly declared private here}}
|
|
template <typename T> class B {};
|
|
// expected-note@+1 3{{implicitly declared private here}}
|
|
static constexpr int num1 = 42;
|
|
|
|
protected:
|
|
// expected-note@+1 13{{declared protected here}}
|
|
class C {};
|
|
// expected-note@+1 2{{declared protected here}}
|
|
static constexpr int num2 = 43;
|
|
static int num4;
|
|
|
|
public:
|
|
template <typename T> class D {};
|
|
static constexpr int num3 = 44;
|
|
};
|
|
int A::num4 = 44;
|
|
|
|
class E : public A {
|
|
|
|
// Declarations
|
|
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T = A::B<int>> void func1();
|
|
template <typename T = A::C> void func2();
|
|
template <typename T = class A::D<int>> void func3();
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> A::B<int> func4();
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> A::B<T> func5();
|
|
template <typename T> class A::C func6();
|
|
template <typename T> class A::D<int> func7();
|
|
// expected-error@+1 2{{is a private member of}}
|
|
template <typename T> void func8(class A::B<T>, int x = A::num1);
|
|
template <typename T> void func9(A::C, A::D<T>, int = A::num3);
|
|
|
|
// Specializations inside class declaration
|
|
template <> void func1<A::B<char>>() {}
|
|
template <> void func2<class A::D<char>>() {
|
|
} template <> void func3<class A::C>() {
|
|
}
|
|
template <> class A::B<int> func4<A::B<char>>() { return {}; } template <> A::B<A::D<int>> func5<A::D<int>>() {
|
|
return {};
|
|
}
|
|
template <> class A::C func6<A::C>() { return {}; } template <> A::D<int> func7<char>() {
|
|
return {};
|
|
}
|
|
template <> void func8<char>(class A::B<char>, int) {}
|
|
template <> void func9<A::B<char>>(A::C, A::D<A::B<char>>, int) {}
|
|
|
|
// FIXME: Instantiations inside class declaration.
|
|
// don't work correctly.
|
|
};
|
|
|
|
// Definitions
|
|
|
|
template <typename T> void E::func1() {}
|
|
template <typename T> void E::func2() {}
|
|
template <typename T> void E::func3() {}
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> A::B<int> E::func4() { return {}; }
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> A::B<T> E::func5() { return {}; }
|
|
template <typename T> A::C E::func6() { return {}; }
|
|
template <typename T> A::D<int> E::func7() { return {}; }
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> void E::func8(A::B<T>, int) {}
|
|
template <typename T> void E::func9(A::C, A::D<T>, int) {}
|
|
|
|
// Specializations
|
|
|
|
template <> void E::func1<A::B<int>>() {}
|
|
template <> void E::func2<class A::C>() {}
|
|
template <> void E::func3<class A::D<int>>() {
|
|
} template <> class A::B<int> E::func4<A::B<int>>() {
|
|
return {};
|
|
} template <> A::B<A::C> E::func5<A::C>() {
|
|
return {};
|
|
}
|
|
template <> class A::C E::func6<A::D<int>>() { return {}; } template <> A::D<int> E::func7<int>() {
|
|
return {};
|
|
}
|
|
template <> void E::func8<int>(class A::B<int>, int) {}
|
|
template <> void E::func9<A::C>(A::C, A::D<A::C>, int) {}
|
|
|
|
// Instantiations
|
|
|
|
template <> void E::func1<A::B<int>>();
|
|
template <> void E::func2<class A::C>();
|
|
template <> void E::func3<class A::D<int>>();
|
|
template <> class A::B<int> E::func4<A::B<int>>();
|
|
template <> A::B<A::C> E::func5<A::C>();
|
|
template <> class A::C E::func6<A::D<int>>();
|
|
template <> A::D<int> E::func7<int>();
|
|
template <> void E::func8<int>(class A::B<int>, int);
|
|
template <> void E::func9<A::C>(A::C, A::D<A::C>, int);
|
|
|
|
//----------------------------------------------------------//
|
|
|
|
// forward declarations
|
|
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> class A::C func1();
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> A::B<T> func2();
|
|
template <typename T> A::D<T> func3();
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> class A::B<int> func4();
|
|
template <typename T> void func5();
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <int x = A::num1> void func6();
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <int x = A::num2> void func7();
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> void func8(int x = sizeof(A::C));
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> void func9(int x = A::num1);
|
|
// expected-error@+2 {{is a private member of}}
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> void func10(class A::B<T>, int x = A::num2);
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> void func11(class A::C, A::D<T>, int = A::num3);
|
|
template <typename T> void func12();
|
|
template <int x> void func13();
|
|
template <typename T, int x> void func14();
|
|
template <template <typename> typename T> void func15();
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T = A::C> void func16();
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T = A::B<int>> void func17();
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> auto func18() -> A::C;
|
|
template <typename T> T func19();
|
|
|
|
//----------------------------------------------------------//
|
|
|
|
// definitions
|
|
|
|
// expected-error@+1 2{{is a protected member of}}
|
|
template <typename T> A::C func1() { A::C x; }
|
|
// expected-error@+2 {{is a private member of}}
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> A::B<T> func2() { A::D<A::C> x; }
|
|
template <typename T> A::D<T> func3() { A::D<int> x; }
|
|
// expected-error@+2 2{{is a private member of}}
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> class A::B<int> func4() { A::B<A::C> x; }
|
|
|
|
template <typename T>
|
|
void func5() {
|
|
// expected-error@+2 {{is a private member of}}
|
|
// expected-error@+1 {{is a protected member of}}
|
|
A::B<A::D<A::C>> x;
|
|
// expected-error@+1 {{is a private member of}}
|
|
A::B<int> x2;
|
|
}
|
|
template <typename T> void func8(int x) {}
|
|
template <typename T> void func9(int x) {}
|
|
// expected-error@+1 {{is a private member of}}
|
|
template <typename T> void func10(A::B<T>, int x) {}
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> void func11(A::C, A::D<T>, int) {}
|
|
template <typename T> void func12() {}
|
|
template <int x> void func13() {}
|
|
template <typename T, int x> void func14() {}
|
|
template <template <typename> typename T> void func15() {}
|
|
template <typename T> void func16() {}
|
|
template <typename T> void func17() {}
|
|
// expected-error@+1 {{is a protected member of}}
|
|
template <typename T> auto func18() -> A::C {
|
|
// expected-error@+1 {{is a protected member of}}
|
|
return A::C{};
|
|
}
|
|
template <typename T> T func19() {
|
|
return T{};
|
|
}
|
|
|
|
//----------------------------------------------------------//
|
|
|
|
// explicit specializations
|
|
|
|
template <> A::C func1<A::C>();
|
|
template <> A::B<A::C> func2<A::C>();
|
|
template <> A::D<A::C> func3<A::C>();
|
|
template <> class A::B<int> func4<A::C>();
|
|
template <> void func5<A::C>();
|
|
template <> void func5<A::B<int>>();
|
|
template <> void func5<A::D<A::C>>();
|
|
template <> void func5<int>();
|
|
template <> void func8<A::C>(int x);
|
|
template <> void func9<decltype(A::num1)>(int);
|
|
template <> void func10<A::D<int>>(A::B<A::D<int>>, int);
|
|
template <> void func11<A::C>(A::C, A::D<A::C>, int);
|
|
template <> void func12<class A::B<char>>() {
|
|
} template <> void func13<A::num1>() {
|
|
}
|
|
template <> void func14<A::B<int>, A::num2>() {}
|
|
template <> void func15<A::D>() {}
|
|
template <> void func16<class A::B<char>>() {
|
|
} template <> void func17<A::B<class A::C>>() {
|
|
}
|
|
template <> auto func18<int>() -> class A::C;
|
|
template <> A::B<int> func19<class A::B<int>>();
|
|
|
|
//----------------------------------------------------------//
|
|
|
|
// explicit instantiations
|
|
|
|
template void func10<A::C>(A::B<A::C>, decltype(A::num1));
|
|
template void func11<A::B<int>>(A::C, A::D<A::B<int>>, decltype(A::num2));
|
|
template void func12<A::C>();
|
|
template void func13<A::num2>();
|
|
template void func13<A::num3>();
|
|
template void func14<A::C, A::num1>();
|
|
template void func15<A::B>();
|
|
template void func17();
|
|
template auto func18<char>() -> A::C;
|
|
template class A::C func19<A::C>();
|
|
|
|
//----------------------------------------------------------//
|
|
|
|
// Other cases
|
|
|
|
template <int *x> class StealClass {
|
|
friend int stealFunc() { return *x; }
|
|
};
|
|
|
|
template class StealClass<&A::num4>;
|
|
int stealFunc();
|
|
|
|
int stealFunc2() {
|
|
return stealFunc();
|
|
}
|