llvm-project/clang/test/SemaTemplate/instantiate-using-decl.cpp
Krystian Stasiowski 5c4b923c72
Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (#87541, #88311)" (#88731)
Reapplies #87541 and #88311 (again) addressing the bug which caused
expressions naming overload sets to be incorrectly rebuilt, as well as
the bug which caused base class members to always be treated as overload
sets.

The primary change since #88311 is `UnresolvedLookupExpr::Create` is called directly in `BuildPossibleImplicitMemberExpr` with `KnownDependent` as `true` (which causes the expression type to be set to `ASTContext::DependentTy`). This ensures that any further semantic analysis involving the type of the potentially implicit class member access expression is deferred until instantiation.
2024-04-22 11:48:13 -04:00

170 lines
4.1 KiB
C++

// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
namespace test0 {
namespace N { }
template<typename T>
struct A {
void f();
};
template<typename T>
struct B : A<T> {
using A<T>::f;
void g() {
using namespace N;
f();
}
};
template struct B<int>;
}
namespace test1 {
template <class Derived> struct Visitor1 {
void Visit(struct Object1*);
};
template <class Derived> struct Visitor2 {
void Visit(struct Object2*); // expected-note {{candidate function}}
};
template <class Derived> struct JoinVisitor
: Visitor1<Derived>, Visitor2<Derived> {
typedef Visitor1<Derived> Base1;
typedef Visitor2<Derived> Base2;
void Visit(struct Object1*); // expected-note {{candidate function}}
using Base2::Visit;
};
class Knot : public JoinVisitor<Knot> {
};
void test() {
Knot().Visit((struct Object1*) 0);
Knot().Visit((struct Object2*) 0);
Knot().Visit((struct Object3*) 0); // expected-error {{no matching member function for call}}
}
}
// PR5847
namespace test2 {
namespace ns {
void foo();
}
template <class T> void bar(T* ptr) {
using ns::foo;
foo();
}
template void bar(char *);
}
namespace test3 {
template <typename T> struct t {
struct s1 {
T f1() const;
};
struct s2 : s1 {
using s1::f1;
T f1() const;
};
};
void f2()
{
t<int>::s2 a;
t<int>::s2 const & b = a;
b.f1();
}
}
namespace PR16936 {
// Make sure both using decls are properly considered for
// overload resolution.
template<class> struct A {
void access(int);
};
template<class> struct B {
void access();
};
template<class CELL> struct X : public A<CELL>, public B<CELL> {
using A<CELL>::access;
using B<CELL>::access;
void f() {
access(0);
}
};
void f() {
X<int> x;
x.f();
}
}
namespace pr21923 {
template <typename> struct Base {
int field;
void method();
};
template <typename Scalar> struct Derived : Base<Scalar> {
using Base<Scalar>::field;
using Base<Scalar>::method;
static void m_fn1() {
// expected-error@+1 {{invalid use of member 'field' in static member function}}
(void)field;
// expected-error@+1 {{invalid use of member 'field' in static member function}}
(void)&field;
// expected-error@+1 {{call to non-static member function without an object argument}}
(void)method;
// expected-error@+1 {{must explicitly qualify name of member function when taking its address}}
(void)&method;
// expected-error@+1 {{call to non-static member function without an object argument}}
method();
(void)&Base<Scalar>::field;
(void)&Base<Scalar>::method;
}
#if __cplusplus >= 201103L
// These usages are OK in C++11 due to the unevaluated context.
enum { TheSize = sizeof(field) };
typedef decltype(field) U;
#else
// expected-error@+1 {{invalid use of non-static data member 'field'}}
enum { TheSize = sizeof(field) };
#endif
};
#if __cplusplus < 201103L
// C++98 has an extra note for TheSize.
// expected-note@+2 {{requested here}}
#endif
template class Derived<int>; // expected-note {{requested here}}
// This is interesting because we form an UnresolvedLookupExpr in the static
// function template and an UnresolvedMemberExpr in the instance function
// template. As a result, we get slightly different behavior.
struct UnresolvedTemplateNames {
template <typename> void maybe_static();
#if __cplusplus < 201103L
// expected-warning@+2 {{default template arguments for a function template are a C++11 extension}}
#endif
template <typename T, typename T::type = 0> static void maybe_static();
template <typename T>
void instance_method() { (void)maybe_static<T>(); }
template <typename T>
static void static_method() {
// expected-error@+1 {{call to non-static member function without an object argument}}
(void)maybe_static<T>();
}
};
void force_instantiation(UnresolvedTemplateNames x) {
x.instance_method<int>();
UnresolvedTemplateNames::static_method<int>(); // expected-note {{requested here}}
}
} // pr21923