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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/dcl.decl/dcl.init/p6.cpp b/test/CXX/dcl.decl/dcl.init/p6.cpp
new file mode 100644
index 0000000..370bafc
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.init/p6.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// FIXME: Very incomplete!
+
+// If a program calls for the default initialization of an object of a
+// const-qualified type T, T shall be a class type with a
+// user-provided default constructor.
+struct NoUserDefault { };
+struct HasUserDefault { HasUserDefault(); };
+
+void test_const_default_init() {
+ const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}}
+ const HasUserDefault x2;
+ const int x3; // FIXME: xpected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}}
+}
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index 53f057e..2efb7b9 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -104,8 +104,8 @@
};
struct N : M {
- N() : M(1), // expected-error {{no matching constructor for initialization of 'M'}}
- m1(100) { } // expected-error {{no matching constructor for initialization of 'm1'}}
+ N() : M(1), // expected-error {{no matching constructor for initialization of 'struct M'}}
+ m1(100) { } // expected-error {{no matching constructor for initialization of 'struct M'}}
M m1;
};
@@ -116,8 +116,8 @@
};
struct Q {
- Q() : f1(1,2), // expected-error {{Too many arguments for member initializer 'f1'}}
- pf(0.0) { } // expected-error {{incompatible type passing 'double', expected 'float *'}}
+ 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'}}
float f1;
float *pf;
diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp
index 315e29a..d7eb5cf 100644
--- a/test/SemaCXX/copy-assignment.cpp
+++ b/test/SemaCXX/copy-assignment.cpp
@@ -47,22 +47,22 @@
void test() {
A a, na;
- const A constA;
+ const A constA = A();
ConvertibleToA convertibleToA;
ConvertibleToConstA convertibleToConstA;
B b, nb;
- const B constB;
+ const B constB = B();
ConvertibleToB convertibleToB;
ConvertibleToBref convertibleToBref;
ConvertibleToConstB convertibleToConstB;
ConvertibleToConstBref convertibleToConstBref;
C c, nc;
- const C constC;
+ const C constC = C();
D d, nd;
- const D constD;
+ const D constD = D();
ConvertibleToInt convertibleToInt;
diff --git a/test/SemaCXX/illegal-member-initialization.cpp b/test/SemaCXX/illegal-member-initialization.cpp
index 1890dbc..be5f91d 100644
--- a/test/SemaCXX/illegal-member-initialization.cpp
+++ b/test/SemaCXX/illegal-member-initialization.cpp
@@ -1,9 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct A {
- A() : value(), cvalue() { } // expected-error {{cannot initialize the member to null in default constructor because reference member 'value' cannot be null-initialized}} \
- // expected-error {{constructor for 'struct A' must explicitly initialize the reference member 'value'}}
- int &value; // expected-note{{declared at}} {{expected-note{{declared at}}
+ A() : value(), cvalue() { } // expected-error {{reference to type 'int' requires an initializer}}
+ int &value;
const int cvalue;
};
@@ -18,7 +17,7 @@
int &value; // expected-note{{declared at}}
const int cvalue; // expected-note{{declared at}}
B& b; // expected-note{{declared at}}
- const B cb; // expected-note{{declared at}}
+ const B cb; // expected-note{{declared here}}
};
diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp
index 22416f3..77d9965 100644
--- a/test/SemaCXX/overload-member-call.cpp
+++ b/test/SemaCXX/overload-member-call.cpp
@@ -89,7 +89,7 @@
A a;
a.foo(4, "hello"); //expected-error {{no matching member function for call to 'foo'}}
- const A b;
+ const A b = A();
b.bar(0); //expected-error {{no matching member function for call to 'bar'}}
a.baz(b); //expected-error {{no matching member function for call to 'baz'}}
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index 861d679..e07afe2 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -344,7 +344,7 @@
int operator[](unsigned); // expected-note {{candidate}}
};
int test1() {
- const NonConstArray x;
+ const NonConstArray x = NonConstArray();
return x[0]; // expected-error {{no viable overloaded operator[] for type}}
}
diff --git a/test/SemaTemplate/instantiate-member-initializers.cpp b/test/SemaTemplate/instantiate-member-initializers.cpp
index f7b7e47..eecb445 100644
--- a/test/SemaTemplate/instantiate-member-initializers.cpp
+++ b/test/SemaTemplate/instantiate-member-initializers.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -Wall -verify %s
template<typename T> struct A {
- A() : a(1) { } // expected-error{{incompatible type passing 'int', expected 'void *'}}
+ A() : a(1) { } // expected-error{{cannot initialize a member subobject of type 'void *' with an rvalue of type 'int'}}
T a;
};