summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp115
1 files changed, 63 insertions, 52 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d75a469970f..573c1af8d20 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14997,6 +14997,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// possibly recursively, a member that is such a structure)
// shall not be a member of a structure or an element of an
// array.
+ bool IsLastField = (i + 1 == Fields.end());
if (FDTy->isFunctionType()) {
// Field declared as a function.
Diag(FD->getLocation(), diag::err_field_declared_as_function)
@@ -15004,60 +15005,70 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
- } else if (FDTy->isIncompleteArrayType() && Record &&
- ((i + 1 == Fields.end() && !Record->isUnion()) ||
- ((getLangOpts().MicrosoftExt ||
- getLangOpts().CPlusPlus) &&
- (i + 1 == Fields.end() || Record->isUnion())))) {
- // Flexible array member.
- // Microsoft and g++ is more permissive regarding flexible array.
- // It will accept flexible array in union and also
- // as the sole element of a struct/class.
- unsigned DiagID = 0;
- if (Record->isUnion())
- DiagID = getLangOpts().MicrosoftExt
- ? diag::ext_flexible_array_union_ms
- : getLangOpts().CPlusPlus
- ? diag::ext_flexible_array_union_gnu
- : diag::err_flexible_array_union;
- else if (NumNamedMembers < 1)
- DiagID = getLangOpts().MicrosoftExt
- ? diag::ext_flexible_array_empty_aggregate_ms
- : getLangOpts().CPlusPlus
- ? diag::ext_flexible_array_empty_aggregate_gnu
- : diag::err_flexible_array_empty_aggregate;
-
- if (DiagID)
- Diag(FD->getLocation(), DiagID) << FD->getDeclName()
- << Record->getTagKind();
- // While the layout of types that contain virtual bases is not specified
- // by the C++ standard, both the Itanium and Microsoft C++ ABIs place
- // virtual bases after the derived members. This would make a flexible
- // array member declared at the end of an object not adjacent to the end
- // of the type.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
- if (RD->getNumVBases() != 0)
- Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+ } else if (FDTy->isIncompleteArrayType() &&
+ (Record || isa<ObjCContainerDecl>(EnclosingDecl))) {
+ if (Record) {
+ // Flexible array member.
+ // Microsoft and g++ is more permissive regarding flexible array.
+ // It will accept flexible array in union and also
+ // as the sole element of a struct/class.
+ unsigned DiagID = 0;
+ if (!Record->isUnion() && !IsLastField) {
+ Diag(FD->getLocation(), diag::err_flexible_array_not_at_end)
+ << FD->getDeclName() << FD->getType() << Record->getTagKind();
+ Diag((*(i + 1))->getLocation(), diag::note_next_field_declaration);
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ } else if (Record->isUnion())
+ DiagID = getLangOpts().MicrosoftExt
+ ? diag::ext_flexible_array_union_ms
+ : getLangOpts().CPlusPlus
+ ? diag::ext_flexible_array_union_gnu
+ : diag::err_flexible_array_union;
+ else if (NumNamedMembers < 1)
+ DiagID = getLangOpts().MicrosoftExt
+ ? diag::ext_flexible_array_empty_aggregate_ms
+ : getLangOpts().CPlusPlus
+ ? diag::ext_flexible_array_empty_aggregate_gnu
+ : diag::err_flexible_array_empty_aggregate;
+
+ if (DiagID)
+ Diag(FD->getLocation(), DiagID) << FD->getDeclName()
+ << Record->getTagKind();
+ // While the layout of types that contain virtual bases is not specified
+ // by the C++ standard, both the Itanium and Microsoft C++ ABIs place
+ // virtual bases after the derived members. This would make a flexible
+ // array member declared at the end of an object not adjacent to the end
+ // of the type.
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
+ if (RD->getNumVBases() != 0)
+ Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+ << FD->getDeclName() << Record->getTagKind();
+ if (!getLangOpts().C99)
+ Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind();
- if (!getLangOpts().C99)
- Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
- << FD->getDeclName() << Record->getTagKind();
- // If the element type has a non-trivial destructor, we would not
- // implicitly destroy the elements, so disallow it for now.
- //
- // FIXME: GCC allows this. We should probably either implicitly delete
- // the destructor of the containing class, or just allow this.
- QualType BaseElem = Context.getBaseElementType(FD->getType());
- if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
- Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
- << FD->getDeclName() << FD->getType();
- FD->setInvalidDecl();
- EnclosingDecl->setInvalidDecl();
- continue;
+ // If the element type has a non-trivial destructor, we would not
+ // implicitly destroy the elements, so disallow it for now.
+ //
+ // FIXME: GCC allows this. We should probably either implicitly delete
+ // the destructor of the containing class, or just allow this.
+ QualType BaseElem = Context.getBaseElementType(FD->getType());
+ if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
+ Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
+ << FD->getDeclName() << FD->getType();
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ }
+ // Okay, we have a legal flexible array member at the end of the struct.
+ Record->setHasFlexibleArrayMember(true);
+ } else {
+ // In ObjCContainerDecl ivars with incomplete array type are accepted,
+ // unless they are followed by another ivar. That check is done
+ // elsewhere, after synthesized ivars are known.
}
- // Okay, we have a legal flexible array member at the end of the struct.
- Record->setHasFlexibleArrayMember(true);
} else if (!FDTy->isDependentType() &&
RequireCompleteType(FD->getLocation(), FD->getType(),
diag::err_field_incomplete)) {
@@ -15074,7 +15085,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// If this is a struct/class and this is not the last element, reject
// it. Note that GCC supports variable sized arrays in the middle of
// structures.
- if (i + 1 != Fields.end())
+ if (!IsLastField)
Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct)
<< FD->getDeclName() << FD->getType();
else {
OpenPOWER on IntegriCloud