mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 21:53:12 +08:00
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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'}}
|
||||
}
|
||||
|
||||
@@ -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 &'}}
|
||||
|
||||
@@ -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!
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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}}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 '('}}
|
||||
}
|
||||
|
||||
|
||||
@@ -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}}
|
||||
}
|
||||
|
||||
@@ -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'}}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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'}}
|
||||
|
||||
@@ -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}}
|
||||
}
|
||||
|
||||
|
||||
@@ -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}}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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::*'}}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user