Initialization improvements: addition of string initialization and a few

small bug fixes in SemaInit, switch over SemaDecl to use it more often, and
change a bunch of diagnostics which are different with the new initialization
code.

llvm-svn: 91767
This commit is contained in:
Eli Friedman
2009-12-19 08:11:05 +00:00
parent 5103effb1d
commit 7827520ce8
22 changed files with 88 additions and 67 deletions

View File

@@ -3525,26 +3525,22 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
VDecl->setInvalidDecl();
} else if (!VDecl->isInvalidDecl()) {
if (VDecl->getType()->isReferenceType()
|| isa<InitListExpr>(Init)) {
InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
if (InitSeq) {
OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
MultiExprArg(*this, (void**)&Init, 1),
&DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
Init = Result.takeAs<Expr>();
} else {
InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
if (InitSeq) {
OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
MultiExprArg(*this, (void**)&Init, 1),
&DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
} else if (CheckInitializerTypes(Init, DclT, Entity, Kind))
}
Init = Result.takeAs<Expr>();
} else {
InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
VDecl->setInvalidDecl();
return;
}
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
// Don't check invalid declarations to avoid emitting useless diagnostics.

View File

@@ -1988,6 +1988,7 @@ void InitializationSequence::Step::Destroy() {
case SK_ConstructorInitialization:
case SK_ZeroInitialization:
case SK_CAssignment:
case SK_StringInit:
break;
case SK_ConversionSequence:
@@ -2080,6 +2081,13 @@ void InitializationSequence::AddCAssignmentStep(QualType T) {
Steps.push_back(S);
}
void InitializationSequence::AddStringInitStep(QualType T) {
Step S;
S.Kind = SK_StringInit;
S.Type = T;
Steps.push_back(S);
}
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
@@ -2492,7 +2500,8 @@ static void TryStringLiteralInitialization(Sema &S,
const InitializationKind &Kind,
Expr *Initializer,
InitializationSequence &Sequence) {
// FIXME: Implement!
Sequence.setSequenceKind(InitializationSequence::StringInit);
Sequence.AddStringInitStep(Entity.getType().getType());
}
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
@@ -2711,10 +2720,17 @@ static void TryUserDefinedConversion(Sema &S,
}
}
}
SourceLocation DeclLoc = Initializer->getLocStart();
if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
// The type we're converting from is a class type, enumerate its conversion
// functions.
// Try to force the type to be complete before enumerating the conversion
// functions; it's okay if this fails, though.
S.RequireCompleteType(DeclLoc, SourceType, 0);
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
@@ -2746,8 +2762,6 @@ static void TryUserDefinedConversion(Sema &S,
}
}
SourceLocation DeclLoc = Initializer->getLocStart();
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
@@ -2876,13 +2890,6 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
// Handle initialization in C
if (!S.getLangOptions().CPlusPlus) {
setSequenceKind(CAssignment);
AddCAssignmentStep(DestType);
return;
}
// - Otherwise, if the destination type is an array, the program is
// ill-formed.
if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
@@ -2893,6 +2900,13 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
// Handle initialization in C
if (!S.getLangOptions().CPlusPlus) {
setSequenceKind(CAssignment);
AddCAssignmentStep(DestType);
return;
}
// - If the destination type is a (possibly cv-qualified) class type:
if (DestType->isRecordType()) {
@@ -3187,6 +3201,7 @@ InitializationSequence::Perform(Sema &S,
case SK_ConversionSequence:
case SK_ListInitialization:
case SK_CAssignment:
case SK_StringInit:
assert(Args.size() == 1);
CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain());
if (CurInit.isInvalid())
@@ -3425,6 +3440,12 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.Owned(CurInitExpr);
break;
}
case SK_StringInit: {
QualType Ty = Step->Type;
CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
break;
}
}
}

View File

@@ -389,7 +389,10 @@ public:
StandardConversion,
/// \brief C conversion sequence.
CAssignment
CAssignment,
/// \brief String initialization
StringInit
};
/// \brief Describes the kind of a particular step in an initialization
@@ -422,7 +425,9 @@ public:
/// \brief Zero-initialize the object
SK_ZeroInitialization,
/// \brief C assignment
SK_CAssignment
SK_CAssignment,
/// \brief Initialization by string
SK_StringInit
};
/// \brief A single step in the initialization sequence.
@@ -632,6 +637,9 @@ public:
// path. However, that isn't the case yet.
void AddCAssignmentStep(QualType T);
/// \brief Add a string init step.
void AddStringInitStep(QualType T);
/// \brief Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;

View File

@@ -7,6 +7,5 @@ void f() {
B b;
A *a = &b; // expected-error{{conversion from 'struct B' to inaccessible base class 'struct A'}} \
expected-error{{incompatible type initializing 'struct B *', expected 'struct A *'}}
A *a = &b; // expected-error{{conversion from 'struct B' to inaccessible base class 'struct A'}}
}

View File

@@ -16,7 +16,7 @@ void f() {
int b;
A a(b);
int A::*ip = &A::s; // expected-error {{incompatible type initializing 'int *', expected 'int class A::*'}}
int A::*ip = &A::s; // expected-error {{cannot initialize a variable of type 'int class A::*' with an rvalue of type 'int *'}}
a.*&A::s = 10; // expected-error{{right hand operand to .* has non pointer-to-member type 'int *'}}
a.*&A::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}}

View File

@@ -5,6 +5,6 @@ template<typename T> T f0(T, T);
void test_f0() {
int (*f0a)(int, int) = f0;
int (*f0b)(int, int) = &f0;
int (*f0c)(int, float) = f0; // expected-error{{incompatible type}}
int (*f0c)(int, float) = f0; // expected-error{{cannot initialize}}
// FIXME: poor error message above!
}

View File

@@ -18,6 +18,6 @@ int f0(int);
void test_f0_2() {
using namespace N;
int (*fp0)(int) = f0; // expected-error{{ambiguous}} \
// expected-error{{initializing}}
// expected-error{{cannot initialize}}
float (*fp1)(float) = f0;
}

View File

@@ -167,7 +167,7 @@ void charArrays() {
void variableArrayInit() {
int a = 4;
char strlit[a] = "foo"; //expected-error{{variable-sized object may not be initialized}}
char strlit[a] = "foo"; //expected-error{{array initializer must be an initializer list or string literal}}
int b[a] = { 1, 2, 4 }; //expected-error{{variable-sized object may not be initialized}}
}

View File

@@ -20,7 +20,7 @@ int *h = &x;
int test() {
int a[10];
int b[10] = a; // expected-error {{initialization with '{...}' expected}}
int b[10] = a; // expected-error {{array initializer must be an initializer list}}
int +; // expected-error {{expected identifier or '('}}
}

View File

@@ -17,6 +17,6 @@ int check_wchar_size[sizeof(*L"") == sizeof(wchar_t) ? 1 : -1];
void foo() {
WCHAR_T_TYPE t1[] = L"x";
wchar_t tab[] = L"x";
WCHAR_T_TYPE t2[] = "x"; // expected-error {{initialization}}
char t3[] = L"x"; // expected-error {{initialization}}
WCHAR_T_TYPE t2[] = "x"; // expected-error {{initializer}}
char t3[] = L"x"; // expected-error {{initializer}}
}

View File

@@ -5,8 +5,7 @@ class A { };
class B : private A { }; // expected-note {{'private' inheritance specifier here}}
void f(B* b) {
A *a = b; // expected-error{{conversion from 'class T1::B' to inaccessible base class 'class T1::A'}} \
expected-error{{incompatible type initializing 'class T1::B *', expected 'class T1::A *'}}
A *a = b; // expected-error{{conversion from 'class T1::B' to inaccessible base class 'class T1::A'}}
}
}
@@ -17,8 +16,7 @@ class A { };
class B : A { }; // expected-note {{inheritance is implicitly 'private'}}
void f(B* b) {
A *a = b; // expected-error {{conversion from 'class T2::B' to inaccessible base class 'class T2::A'}} \
expected-error {{incompatible type initializing 'class T2::B *', expected 'class T2::A *'}}
A *a = b; // expected-error {{conversion from 'class T2::B' to inaccessible base class 'class T2::A'}}
}
}
@@ -71,8 +69,7 @@ namespace T6 {
class C : public B {
void f(C *c) {
A* a = c; // expected-error {{conversion from 'class T6::C' to inaccessible base class 'class T6::A'}} \
expected-error {{incompatible type initializing 'class T6::C *', expected 'class T6::A *'}}
A* a = c; // expected-error {{conversion from 'class T6::C' to inaccessible base class 'class T6::A'}}
}
};

View File

@@ -14,7 +14,7 @@ void test(bool b)
--b; // expected-error {{cannot decrement expression of type bool}}
b--; // expected-error {{cannot decrement expression of type bool}}
bool *b1 = (int *)0; // expected-error{{expected 'bool *'}}
bool *b1 = (int *)0; // expected-error{{cannot initialize}}
}
// static_assert_arg_is_bool(x) compiles only if x is a bool.

View File

@@ -6,7 +6,7 @@ void test() {
if (int x=0) ++x;
typedef int arr[10];
while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{initialization with '{...}' expected for array}}
while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}}
while (int f()=0) ; // expected-error {{a function type is not allowed here}}
struct S {} s;
@@ -18,7 +18,7 @@ void test() {
while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} expected-note{{candidate function}}
while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct <anonymous>' is not contextually convertible to 'bool'}} expected-note{{candidate function}}
switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}}
switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}}
if (int x=0) { // expected-note 2 {{previous definition is here}}
int x; // expected-error {{redefinition of 'x'}}

View File

@@ -44,7 +44,7 @@ struct ExplicitConvToRef {
void test_explicit_bool(ExplicitConvToBool ecb) {
bool b1(ecb); // okay
bool b2 = ecb; // expected-error{{incompatible type initializing 'struct ExplicitConvToBool', expected 'bool'}}
bool b2 = ecb; // expected-error{{no viable conversion from 'struct ExplicitConvToBool' to 'bool'}}
accepts_bool(ecb); // expected-error{{no matching function for call to}}
}

View File

@@ -18,7 +18,7 @@ void ov(double) = delete; // expected-note {{candidate function has been explici
struct WithDel {
WithDel() = delete; // expected-note {{candidate function has been explicitly deleted}}
void fn() = delete; // expected-note {{function has been explicitly marked deleted here}}
operator int() = delete;
operator int() = delete; // expected-note {{function has been explicitly marked deleted here}}
void operator +(int) = delete;
int i = delete; // expected-error {{only functions can have deleted definitions}}
@@ -32,5 +32,5 @@ void test() {
WithDel dd; // expected-error {{call to deleted constructor of 'dd'}}
WithDel *d = 0;
d->fn(); // expected-error {{attempt to use a deleted function}}
int i = *d; // expected-error {{incompatible type initializing}}
int i = *d; // expected-error {{invokes a deleted function}}
}

View File

@@ -40,11 +40,11 @@ struct Base {
};
struct Derived : Base {
operator int*();
operator int*(); // expected-note {{candidate function}}
};
void foo(const Derived cd, Derived d) {
int *pi = cd; // expected-error {{incompatible type initializing 'struct Derived const', expected 'int *'}}
int *pi = cd; // expected-error {{no viable conversion from 'struct Derived const' to 'int *'}}
int *ppi = d;
}

View File

@@ -160,11 +160,11 @@ void fnptrs()
// return types and arguments must match exactly, no inheritance allowed
void (*(*t7)())() throw(B1) = &s8; // valid
void (*(*t8)())() throw(A) = &s8; // expected-error {{return types differ}} expected-error {{incompatible type}}
void (*(*t9)())() throw(D) = &s8; // expected-error {{return types differ}} expected-error {{incompatible type}}
void (*(*t8)())() throw(A) = &s8; // expected-error {{return types differ}}
void (*(*t9)())() throw(D) = &s8; // expected-error {{return types differ}}
void (*t10)(void (*)() throw(B1)) = &s9; // valid expected-warning{{disambiguated}}
void (*t11)(void (*)() throw(A)) = &s9; // expected-error {{argument types differ}} expected-error {{incompatible type}} expected-warning{{disambiguated}}
void (*t12)(void (*)() throw(D)) = &s9; // expected-error {{argument types differ}} expected-error {{incompatible type}} expected-warning{{disambiguated}}
void (*t11)(void (*)() throw(A)) = &s9; // expected-error {{argument types differ}} expected-warning{{disambiguated}}
void (*t12)(void (*)() throw(D)) = &s9; // expected-error {{argument types differ}} expected-warning{{disambiguated}}
}
// Member function stuff
@@ -178,7 +178,7 @@ void mfnptr()
{
void (Str1::*pfn1)() throw(int) = &Str1::f; // valid
void (Str1::*pfn2)() = &Str1::f; // valid
void (Str1::*pfn3)() throw() = &Str1::f; // expected-error {{not superset}} expected-error {{incompatible type}}
void (Str1::*pfn3)() throw() = &Str1::f; // expected-error {{not superset}}
}
// Don't suppress errors in template instantiation.

View File

@@ -35,8 +35,8 @@ void f() {
pdid = pdi2;
// Fail conversion due to ambiguity and virtuality.
int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'struct A' to pointer to member of derived class 'struct F'}} expected-error {{incompatible type}}
int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'struct A' to pointer to member of class 'struct G' via virtual base 'struct D' is not allowed}} expected-error {{incompatible type}}
int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'struct A' to pointer to member of derived class 'struct F'}}
int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'struct A' to pointer to member of class 'struct G' via virtual base 'struct D' is not allowed}}
// Conversion to member of base.
pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}}

View File

@@ -29,7 +29,7 @@ nullptr_t f(nullptr_t null)
bool b = nullptr;
// Can't convert nullptr to integral implicitly.
uintptr_t i = nullptr; // expected-error {{incompatible type initializing}}
uintptr_t i = nullptr; // expected-error {{cannot initialize}}
// Operators
(void)(null == nullptr);

View File

@@ -27,11 +27,11 @@ void f1(id x, A *a) {
}
void f2(id<P1> x) {
id<P0> l = x; // expected-error {{incompatible type initializing 'id<P1>', expected 'id<P0>'}}
id<P0> l = x; // expected-error {{cannot initialize a variable of type 'id<P0>' with an lvalue of type 'id<P1>'}}
}
void f3(A *a) {
id<P1> l = a; // expected-error {{incompatible type initializing 'A *', expected 'id<P1>'}}
id<P1> l = a; // expected-error {{cannot initialize a variable of type 'id<P1>' with an lvalue of type 'A *'}}
}
void f4(int cond, id x, A *a) {

View File

@@ -8,7 +8,7 @@
// Fake typeid, lacking a typeinfo header.
namespace std { class type_info {}; }
struct dummy {}; // expected-note{{candidate function}}
struct dummy {}; // expected-note 3 {{candidate function}}
template<typename T>
int f0(T x) {
@@ -39,9 +39,9 @@ T f1(T t1, U u1, int i1)
new (t1, u1) int;
delete t1;
dummy d1 = sizeof(t1); // FIXME: delayed checking okay?
dummy d1 = sizeof(t1); // expected-error {{no viable conversion}}
dummy d2 = offsetof(T, foo); // expected-error {{no viable conversion}}
dummy d3 = __alignof(u1); // FIXME: delayed checking okay?
dummy d3 = __alignof(u1); // expected-error {{no viable conversion}}
i1 = typeid(t1); // expected-error {{incompatible type assigning}}
return u1;

View File

@@ -79,7 +79,7 @@ template<class T> struct A1;
int *a(A0<int> &x0, A1<int> &x1) {
int *y0 = x0;
int *y1 = x1; // expected-error{{initializing}}
int *y1 = x1; // expected-error{{no viable conversion}}
}
struct X0Base {