Don't build member initializers for zero-length or incomplete arrays,
and don't try to destroy them, either. Fixes <rdar://problem/10228639>. llvm-svn: 143584
This commit is contained in:
parent
10317eaa28
commit
10f939c3db
|
@ -2413,7 +2413,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
|
|||
// Suppress copying zero-width bitfields.
|
||||
if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
|
||||
return false;
|
||||
|
||||
|
||||
Expr *MemberExprBase =
|
||||
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param,
|
||||
Loc, ParamType, VK_LValue, 0);
|
||||
|
@ -2649,6 +2649,22 @@ static bool isWithinAnonymousUnion(IndirectFieldDecl *F) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given type is an incomplete or zero-lenfgth
|
||||
/// array type.
|
||||
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
|
||||
if (T->isIncompleteArrayType())
|
||||
return true;
|
||||
|
||||
while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
|
||||
if (!ArrayT->getSize())
|
||||
return true;
|
||||
|
||||
T = ArrayT->getElementType();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
|
||||
FieldDecl *Field,
|
||||
IndirectFieldDecl *Indirect = 0) {
|
||||
|
@ -2684,6 +2700,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
|
|||
(Indirect && isWithinAnonymousUnion(Indirect)))
|
||||
return false;
|
||||
|
||||
// Don't initialize incomplete or zero-length arrays.
|
||||
if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
|
||||
return false;
|
||||
|
||||
// Don't try to build an implicit initializer if there were semantic
|
||||
// errors in any of the initializers (and therefore we might be
|
||||
// missing some that the user actually wrote).
|
||||
|
@ -2822,13 +2842,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
|
|||
// initialized.
|
||||
if (F->isUnnamedBitfield())
|
||||
continue;
|
||||
|
||||
if (F->getType()->isIncompleteArrayType()) {
|
||||
assert(ClassDecl->hasFlexibleArrayMember() &&
|
||||
"Incomplete array type is not valid");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// If we're not generating the implicit copy/move constructor, then we'll
|
||||
// handle anonymous struct/union fields based on their individual
|
||||
// indirect fields.
|
||||
|
@ -3169,6 +3183,11 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
|
|||
FieldDecl *Field = *I;
|
||||
if (Field->isInvalidDecl())
|
||||
continue;
|
||||
|
||||
// Don't destroy incomplete or zero-length arrays.
|
||||
if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
|
||||
continue;
|
||||
|
||||
QualType FieldType = Context.getBaseElementType(Field->getType());
|
||||
|
||||
const RecordType* RT = FieldType->getAs<RecordType>();
|
||||
|
|
|
@ -111,7 +111,5 @@ namespace test1 {
|
|||
B::B() {}
|
||||
// CHECK: define void @_ZN5test11BC2Ev(
|
||||
// CHECK: [[THIS:%.*]] = load [[B:%.*]]**
|
||||
// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[B:%.*]]* [[THIS]], i32 0, i32 1
|
||||
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [0 x {{%.*}}]* [[A]], i32 0, i32 0
|
||||
// CHECK-NEXT: ret void
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
// <rdar://problem/10228639>
|
||||
class Foo {
|
||||
~Foo();
|
||||
Foo(const Foo&);
|
||||
public:
|
||||
Foo(int);
|
||||
};
|
||||
|
||||
class Bar {
|
||||
int foo_count;
|
||||
Foo foos[0];
|
||||
Foo foos2[0][2];
|
||||
Foo foos3[2][0];
|
||||
|
||||
public:
|
||||
Bar(): foo_count(0) { }
|
||||
~Bar() { }
|
||||
};
|
||||
|
||||
void testBar() {
|
||||
Bar b;
|
||||
Bar b2(b);
|
||||
b = b2;
|
||||
}
|
Loading…
Reference in New Issue