2009-12-16 04:14:24 +08:00
|
|
|
// RUN: %clang_cc1 -Wreorder -fsyntax-only -verify %s
|
2008-11-05 12:29:56 +08:00
|
|
|
class A {
|
|
|
|
int m;
|
2010-04-10 03:03:51 +08:00
|
|
|
public:
|
2009-07-01 07:26:25 +08:00
|
|
|
A() : A::m(17) { } // expected-error {{member initializer 'm' does not name a non-static data member or base class}}
|
2009-07-23 08:42:24 +08:00
|
|
|
A(int);
|
2008-11-05 12:29:56 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class B : public A {
|
|
|
|
public:
|
|
|
|
B() : A(), m(1), n(3.14) { }
|
|
|
|
|
|
|
|
private:
|
|
|
|
int m;
|
|
|
|
float n;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class C : public virtual B {
|
|
|
|
public:
|
|
|
|
C() : B() { }
|
|
|
|
};
|
|
|
|
|
|
|
|
class D : public C {
|
|
|
|
public:
|
|
|
|
D() : B(), C() { }
|
|
|
|
};
|
|
|
|
|
|
|
|
class E : public D, public B {
|
|
|
|
public:
|
2010-03-10 19:27:22 +08:00
|
|
|
E() : B(), D() { } // expected-error{{base class initializer 'B' names both a direct base class and an inherited virtual base class}}
|
2008-11-05 12:29:56 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef int INT;
|
|
|
|
|
|
|
|
class F : public B {
|
|
|
|
public:
|
|
|
|
int B;
|
|
|
|
|
|
|
|
F() : B(17),
|
|
|
|
m(17), // expected-error{{member initializer 'm' does not name a non-static data member or base class}}
|
2009-02-20 07:45:49 +08:00
|
|
|
INT(17) // expected-error{{constructor initializer 'INT' (aka 'int') does not name a class}}
|
2008-11-05 12:29:56 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
2008-11-11 00:59:40 +08:00
|
|
|
|
|
|
|
class G : A {
|
|
|
|
G() : A(10); // expected-error{{expected '{'}}
|
|
|
|
};
|
2009-03-25 10:58:17 +08:00
|
|
|
|
|
|
|
void f() : a(242) { } // expected-error{{only constructors take base initializers}}
|
|
|
|
|
|
|
|
class H : A {
|
|
|
|
H();
|
|
|
|
};
|
|
|
|
|
|
|
|
H::H() : A(10) { }
|
|
|
|
|
2009-07-01 01:34:52 +08:00
|
|
|
|
|
|
|
class X {};
|
|
|
|
class Y {};
|
|
|
|
|
|
|
|
struct S : Y, virtual X {
|
|
|
|
S ();
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Z : S {
|
2010-03-10 19:27:22 +08:00
|
|
|
Z() : X(), S(), E() {} // expected-error {{type 'E' is not a direct or virtual base of 'Z'}}
|
2009-07-01 01:34:52 +08:00
|
|
|
};
|
|
|
|
|
2009-07-01 05:52:59 +08:00
|
|
|
class U {
|
|
|
|
union { int a; char* p; };
|
|
|
|
union { int b; double d; };
|
|
|
|
|
2010-04-10 17:28:51 +08:00
|
|
|
U() : a(1), // expected-note {{previous initialization is here}}
|
2011-11-17 14:01:57 +08:00
|
|
|
p(0), // expected-error {{initializing multiple members of union}}
|
2010-04-10 17:28:51 +08:00
|
|
|
d(1.0) {}
|
2009-07-01 05:52:59 +08:00
|
|
|
};
|
|
|
|
|
2009-07-01 07:26:25 +08:00
|
|
|
struct V {};
|
|
|
|
struct Base {};
|
|
|
|
struct Base1 {};
|
|
|
|
|
|
|
|
struct Derived : Base, Base1, virtual V {
|
|
|
|
Derived ();
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Current : Derived {
|
|
|
|
int Derived;
|
2010-04-10 15:37:23 +08:00
|
|
|
Current() : Derived(1), ::Derived(), // expected-warning {{field 'Derived' will be initialized after base '::Derived'}} \
|
|
|
|
// expected-warning {{base class '::Derived' will be initialized after base 'Derived::V'}}
|
2009-07-01 07:26:25 +08:00
|
|
|
::Derived::Base(), // expected-error {{type '::Derived::Base' is not a direct or virtual base of 'Current'}}
|
|
|
|
Derived::Base1(), // expected-error {{type 'Derived::Base1' is not a direct or virtual base of 'Current'}}
|
2010-04-10 15:37:23 +08:00
|
|
|
Derived::V(),
|
2009-07-01 07:26:25 +08:00
|
|
|
::NonExisting(), // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}}
|
|
|
|
INT::NonExisting() {} // expected-error {{expected a class or namespace}} \
|
2009-09-09 23:08:12 +08:00
|
|
|
// expected-error {{member initializer 'NonExisting' does not name a non-static data member or}}
|
2009-07-01 07:26:25 +08:00
|
|
|
};
|
2009-07-24 07:32:59 +08:00
|
|
|
|
2010-01-13 08:25:19 +08:00
|
|
|
struct M { // expected-note 2 {{candidate constructor (the implicit copy constructor)}} \
|
2009-11-09 09:05:47 +08:00
|
|
|
// expected-note {{declared here}} \
|
|
|
|
// expected-note {{declared here}}
|
2010-01-06 17:43:14 +08:00
|
|
|
M(int i, int j); // expected-note 2 {{candidate constructor}}
|
2009-07-24 07:32:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct N : M {
|
2010-03-10 19:27:22 +08:00
|
|
|
N() : M(1), // expected-error {{no matching constructor for initialization of 'M'}}
|
|
|
|
m1(100) { } // expected-error {{no matching constructor for initialization of 'M'}}
|
2009-07-24 07:32:59 +08:00
|
|
|
M m1;
|
|
|
|
};
|
|
|
|
|
2009-11-09 09:05:47 +08:00
|
|
|
struct P : M {
|
2010-03-10 19:27:22 +08:00
|
|
|
P() { } // expected-error {{constructor for 'P' must explicitly initialize the base class 'M' which does not have a default constructor}} \
|
2009-11-09 09:05:47 +08:00
|
|
|
// expected-error {{member 'm'}}
|
|
|
|
M m; // expected-note {{member is declared here}}
|
2009-07-24 07:32:59 +08:00
|
|
|
};
|
|
|
|
|
2009-07-25 04:28:49 +08:00
|
|
|
struct Q {
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
Q() : f1(1,2), // expected-error {{excess elements in scalar initializer}}
|
|
|
|
pf(0.0) { } // expected-error {{cannot initialize a member subobject of type 'float *' with an rvalue of type 'double'}}
|
2009-07-25 04:28:49 +08:00
|
|
|
float f1;
|
|
|
|
|
|
|
|
float *pf;
|
|
|
|
};
|
2009-11-05 07:02:40 +08:00
|
|
|
|
|
|
|
// A silly class used to demonstrate field-is-uninitialized in constructors with
|
|
|
|
// multiple params.
|
2010-04-10 03:03:51 +08:00
|
|
|
class TwoInOne { public: TwoInOne(TwoInOne a, TwoInOne b) {} };
|
2009-11-05 07:02:40 +08:00
|
|
|
class InitializeUsingSelfTest {
|
|
|
|
bool A;
|
|
|
|
char* B;
|
|
|
|
int C;
|
|
|
|
TwoInOne D;
|
|
|
|
InitializeUsingSelfTest(int E)
|
|
|
|
: A(A), // expected-warning {{field is uninitialized when used here}}
|
|
|
|
B((((B)))), // expected-warning {{field is uninitialized when used here}}
|
|
|
|
C(A && InitializeUsingSelfTest::C), // expected-warning {{field is uninitialized when used here}}
|
|
|
|
D(D, // expected-warning {{field is uninitialized when used here}}
|
|
|
|
D) {} // expected-warning {{field is uninitialized when used here}}
|
|
|
|
};
|
|
|
|
|
|
|
|
int IntWrapper(int i) { return 0; };
|
|
|
|
class InitializeUsingSelfExceptions {
|
|
|
|
int A;
|
|
|
|
int B;
|
2010-09-21 18:47:20 +08:00
|
|
|
int C;
|
|
|
|
void *P;
|
2009-11-05 07:02:40 +08:00
|
|
|
InitializeUsingSelfExceptions(int B)
|
|
|
|
: A(IntWrapper(A)), // Due to a conservative implementation, we do not report warnings inside function/ctor calls even though it is possible to do so.
|
2010-09-21 18:47:20 +08:00
|
|
|
B(B), // Not a warning; B is a local variable.
|
|
|
|
C(sizeof(C)), // sizeof doesn't reference contents, do not warn
|
|
|
|
P(&P) {} // address-of doesn't reference contents (the pointer may be dereferenced in the same expression but it would be rare; and weird)
|
2009-11-05 07:02:40 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class CopyConstructorTest {
|
|
|
|
bool A, B, C;
|
|
|
|
CopyConstructorTest(const CopyConstructorTest& rhs)
|
|
|
|
: A(rhs.A),
|
|
|
|
B(B), // expected-warning {{field is uninitialized when used here}}
|
|
|
|
C(rhs.C || C) { } // expected-warning {{field is uninitialized when used here}}
|
|
|
|
};
|
2009-11-15 16:51:10 +08:00
|
|
|
|
|
|
|
// Make sure we aren't marking default constructors when we shouldn't be.
|
|
|
|
template<typename T>
|
|
|
|
struct NDC {
|
|
|
|
T &ref;
|
|
|
|
|
|
|
|
NDC() { }
|
|
|
|
NDC(T &ref) : ref(ref) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct X0 : NDC<int> {
|
|
|
|
X0(int &ref) : NDC<int>(ref), ndc(ref) { }
|
|
|
|
|
|
|
|
NDC<int> ndc;
|
|
|
|
};
|
2010-04-23 11:07:47 +08:00
|
|
|
|
|
|
|
namespace Test0 {
|
|
|
|
|
|
|
|
struct A { A(); };
|
|
|
|
|
|
|
|
struct B {
|
|
|
|
B() { }
|
|
|
|
const A a;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
2010-04-24 02:46:30 +08:00
|
|
|
|
2010-04-25 09:00:05 +08:00
|
|
|
namespace Test1 {
|
2010-04-24 02:46:30 +08:00
|
|
|
struct A {
|
|
|
|
enum Kind { Foo } Kind;
|
|
|
|
A() : Kind(Foo) {}
|
|
|
|
};
|
|
|
|
}
|
2010-04-25 09:00:05 +08:00
|
|
|
|
|
|
|
namespace Test2 {
|
|
|
|
|
|
|
|
struct A {
|
|
|
|
A(const A&);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct B : virtual A { };
|
|
|
|
struct C : A, B { };
|
|
|
|
|
|
|
|
C f(C c) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-06-30 10:59:29 +08:00
|
|
|
|
|
|
|
// Don't build implicit initializers for anonymous union fields when we already
|
|
|
|
// have an explicit initializer for another field in the union.
|
|
|
|
namespace PR7402 {
|
|
|
|
struct S {
|
|
|
|
union {
|
|
|
|
void* ptr_;
|
|
|
|
struct { int i_; };
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T> S(T) : ptr_(0) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
void f() {
|
|
|
|
S s(3);
|
|
|
|
}
|
|
|
|
}
|
2010-08-17 15:23:57 +08:00
|
|
|
|
|
|
|
// <rdar://problem/8308215>: don't crash.
|
|
|
|
// Lots of questionable recovery here; errors can change.
|
|
|
|
namespace test3 {
|
|
|
|
class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 3 {{candidate}} expected-note {{passing argument}}
|
|
|
|
class B : public A {
|
|
|
|
public:
|
|
|
|
B(const String& s, int e=0) // expected-error {{unknown type name}}
|
|
|
|
: A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}}
|
|
|
|
B(const B& e)
|
|
|
|
: A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{no viable conversion}} expected-error {{does not name}}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2010-10-06 10:43:25 +08:00
|
|
|
|
|
|
|
// PR8075
|
|
|
|
namespace PR8075 {
|
|
|
|
|
|
|
|
struct S1 {
|
|
|
|
enum { FOO = 42 };
|
|
|
|
static const int bar = 42;
|
|
|
|
static int baz();
|
|
|
|
S1(int);
|
|
|
|
};
|
|
|
|
|
|
|
|
const int S1::bar;
|
|
|
|
|
|
|
|
struct S2 {
|
|
|
|
S1 s1;
|
|
|
|
S2() : s1(s1.FOO) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct S3 {
|
|
|
|
S1 s1;
|
|
|
|
S3() : s1(s1.bar) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct S4 {
|
|
|
|
S1 s1;
|
|
|
|
S4() : s1(s1.baz()) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|