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:
Douglas Gregor 2011-11-02 23:04:16 +00:00
parent 10317eaa28
commit 10f939c3db
3 changed files with 53 additions and 10 deletions

View File

@ -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>();

View File

@ -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
}

View File

@ -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;
}