llvm-project/clang/test/SemaTemplate/instantiate-member-class.cpp
David Blaikie 1c7c8f7637 Implement warning for integral null pointer constants other than the literal 0.
This is effectively a warning for code that violates core issue 903 & thus will
become standard error in the future, hopefully. It catches strange null
pointers such as: '\0', 1 - 1, const int null = 0; etc...

There's currently a flaw in this warning (& the warning for 'false' as a null
pointer literal as well) where it doesn't trigger on comparisons (ptr == '\0'
for example). Fix to come in a future patch.

Also, due to this only being a warning, not an error, it triggers quite
frequently on gtest code which tests expressions for null-pointer-ness in a
SFINAE context (so it wouldn't be a problem if this was an error as in an
actual implementation of core issue 903). To workaround this for now, the
diagnostic does not fire in unevaluated contexts.

Review by Sean Silva and Richard Smith.

llvm-svn: 161501
2012-08-08 17:33:31 +00:00

144 lines
3.5 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify %s
namespace PR8965 {
template<typename T>
struct X {
typedef int type;
T field; // expected-note{{in instantiation of member class}}
};
template<typename T>
struct Y {
struct Inner;
typedef typename X<Inner>::type // expected-note{{in instantiation of template class}}
type; // expected-note{{not-yet-instantiated member is declared here}}
struct Inner {
typedef type field; // expected-error{{no member 'type' in 'PR8965::Y<int>'; it has not yet been instantiated}}
};
};
Y<int> y; // expected-note{{in instantiation of template class}}
}
template<typename T>
class X {
public:
struct C { T &foo(); };
struct D {
struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}}
struct F; // expected-note{{member is declared here}}
};
};
X<int>::C *c1;
X<float>::C *c2;
X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
void test_naming() {
c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}}
xi = xf; // expected-error{{assigning to 'X<int>::X<int> *' from incompatible type 'X<float>::X<float> *'}}
// FIXME: error above doesn't print the type X<int>::X cleanly!
}
void test_instantiation(X<double>::C *x,
X<float>::D::E *e,
X<float>::D::F *f) {
double &dr = x->foo();
float &fr = e->bar();
f->foo(); // expected-error{{implicit instantiation of undefined member 'X<float>::D::F'}}
}
X<void>::C *c3; // okay
X<void>::D::E *e1; // okay
X<void>::D::E e2; // expected-note{{in instantiation of member class 'X<void>::D::E' requested here}}
// Redeclarations.
namespace test1 {
template <typename T> struct Registry {
struct node;
static node *Head;
struct node {
node(int v) { Head = this; }
};
};
void test() {
Registry<int>::node node(0);
}
}
// Redeclarations during explicit instantiations.
namespace test2 {
template <typename T> class A {
class Foo;
class Foo {
int foo();
};
};
template class A<int>;
template <typename T> class B {
class Foo;
class Foo {
public:
typedef int X;
};
typename Foo::X x;
class Foo;
};
template class B<int>;
template <typename T> class C {
class Foo;
class Foo;
};
template <typename T> class C<T>::Foo {
int x;
};
template class C<int>;
}
namespace AliasTagDef {
template<typename T>
struct F {
using S = struct U { // expected-warning {{C++11}}
T g() {
return T();
}
};
};
int m = F<int>::S().g();
int n = F<int>::U().g();
}
namespace rdar10397846 {
template<int I> struct A
{
struct B
{
struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
};
};
template<int N> void foo()
{
class A<N>::B::C X; // expected-note 2 {{in instantiation of member function}}
int A<N+1>::B::C::*member = 0;
}
void bar()
{
foo<0>(); // expected-note{{in instantiation of function template}}
foo<1>(); // expected-note{{in instantiation of function template}}
}
}