Hi rsmith, rnk, andreadb,
Zero sized arrays are more or less the pre-standard version of flexible
array members. It makes sense to mark structs which contain them as
hasFlexibleArrayMember.
Doing this has the side effect of resolving PR21040, a crash involving
one record inheriting from a base which is terminated with a zero sized
array field.
http://reviews.llvm.org/D5478
Files:
include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/Analysis/dtors-in-dtor-cfg-output.cpp
test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
test/CodeGenObjC/arc-captured-block-var-layout.m
test/SemaCXX/flexible-array-test.cpp
test/SemaCXX/zero-length-arrays.cpp
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1910,6 +1910,10 @@
/// \brief Return number of constant array elements.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
+ /// \brief Determine whether the given type is an incomplete or zero-length
+ /// array type.
+ bool isIncompleteOrZeroLengthArrayType(QualType T) const;
+
/// \brief Perform adjustment on the parameter type of a function.
///
/// This routine adjusts the given parameter type @p T to the actual
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -4323,6 +4323,20 @@
return ElementCount;
}
+bool ASTContext::isIncompleteOrZeroLengthArrayType(QualType T) const {
+ if (T->isIncompleteArrayType())
+ return true;
+
+ while (const ConstantArrayType *ArrayT = getAsConstantArrayType(T)) {
+ if (!ArrayT->getSize())
+ return true;
+
+ T = ArrayT->getElementType();
+ }
+
+ return false;
+}
+
/// getFloatingRank - Return a relative rank for floating point types.
/// This routine will assert if passed a built-in type that isn't a float.
static FloatingRank getFloatingRank(QualType T) {
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -12618,7 +12618,7 @@
FieldDecl *FD = cast<FieldDecl>(*i);
// Get the type for the field.
- const Type *FDTy = FD->getType().getTypePtr();
+ QualType FDTy = FD->getType();
if (!FD->isAnonymousStructOrUnion()) {
// Remember all fields written by the user.
@@ -12649,10 +12649,9 @@
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
- } else if (FDTy->isIncompleteArrayType() && Record &&
+ } else if (Context.isIncompleteOrZeroLengthArrayType(FDTy) && Record &&
((i + 1 == Fields.end() && !Record->isUnion()) ||
- ((getLangOpts().MicrosoftExt ||
- getLangOpts().CPlusPlus) &&
+ ((getLangOpts().MicrosoftExt || getLangOpts().CPlusPlus) &&
(i + 1 == Fields.end() || Record->isUnion())))) {
// Flexible array member.
// Microsoft and g++ is more permissive regarding flexible array.
@@ -12674,7 +12673,7 @@
? diag::err_flexible_array_empty_aggregate
: 0;
- if (DiagID)
+ if (DiagID && FDTy->isIncompleteArrayType())
Diag(FD->getLocation(), DiagID) << FD->getDeclName()
<< Record->getTagKind();
// While the layout of types that contain virtual bases is not specified
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -3526,22 +3526,6 @@
};
}
-/// \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 = nullptr) {
@@ -3586,7 +3570,7 @@
}
// Don't initialize incomplete or zero-length arrays.
- if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
+ if (SemaRef.Context.isIncompleteOrZeroLengthArrayType(Field->getType()))
return false;
// Don't try to build an implicit initializer if there were semantic
@@ -4071,7 +4055,7 @@
continue;
// Don't destroy incomplete or zero-length arrays.
- if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+ if (Context.isIncompleteOrZeroLengthArrayType(Field->getType()))
continue;
QualType FieldType = Context.getBaseElementType(Field->getType());
Index: test/Analysis/dtors-in-dtor-cfg-output.cpp
===================================================================
--- test/Analysis/dtors-in-dtor-cfg-output.cpp
+++ test/Analysis/dtors-in-dtor-cfg-output.cpp
@@ -27,7 +27,6 @@
class TestArray {
A a[2];
- A b[0];
public:
~TestArray();
};
Index: test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
===================================================================
--- test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
+++ test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
@@ -152,10 +152,10 @@
void arr3() {
struct S {
int a;
- __unsafe_unretained id unsafe_unretained_var[0];
+ __unsafe_unretained id unsafe_unretained_var[7];
} imported_s;
-// CHECK: block variable layout: BL_OPERATOR:0
+// CHECK: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:7, BL_OPERATOR:0
void (^c)() = ^{
int i = imported_s.a;
};
Index: test/CodeGenObjC/arc-captured-block-var-layout.m
===================================================================
--- test/CodeGenObjC/arc-captured-block-var-layout.m
+++ test/CodeGenObjC/arc-captured-block-var-layout.m
@@ -151,10 +151,10 @@
void arr3() {
struct S {
int a;
- __unsafe_unretained id unsafe_unretained_var[0];
+ __unsafe_unretained id unsafe_unretained_var[7];
} imported_s;
-// CHECK-LP64: block variable layout: BL_OPERATOR:0
+// CHECK-LP64: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:7, BL_OPERATOR:0
void (^c)() = ^{
int i = imported_s.a;
};
Index: test/SemaCXX/flexible-array-test.cpp
===================================================================
--- test/SemaCXX/flexible-array-test.cpp
+++ test/SemaCXX/flexible-array-test.cpp
@@ -94,3 +94,15 @@
ntd[i-1].~NonTrivDtor();
}
};
+
+namespace PR21040 {
+struct A {
+ int a0[0];
+};
+
+struct B : private A { // expected-error {{base class 'A' has a flexible array member}}
+ int b;
+};
+
+B bb;
+}
Index: test/SemaCXX/zero-length-arrays.cpp
===================================================================
--- test/SemaCXX/zero-length-arrays.cpp
+++ test/SemaCXX/zero-length-arrays.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
// <rdar://problem/10228639>
class Foo {
@@ -11,9 +10,7 @@
class Bar {
int foo_count;
- Foo foos[0];
- Foo foos2[0][2];
- Foo foos3[2][0];
+ Foo foos[0]; // expected-error-re {{flexible array member {{.*}} with non-trivial destruction}}
public:
Bar(): foo_count(0) { }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits