diff --git a/clang/AST/SemaType.cpp b/clang/AST/SemaType.cpp index b0ed8c23b72b..153686e3455f 100644 --- a/clang/AST/SemaType.cpp +++ b/clang/AST/SemaType.cpp @@ -133,23 +133,26 @@ TypeRef Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { Type *CanonicalT = T->getCanonicalType(); - // If the element type is a struct or union that contains a variadic - // array, reject it: C99 6.7.2.1p2. - if (RecordType *EltTy = dyn_cast(CanonicalT)) { + // C99 6.7.5.2p1: If the element type is an incomplete or function type, + // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) + if (T->isIncompleteType()) { + Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type, + D.getIdentifier()->getName()); + return TypeRef(); + } else if (isa(CanonicalT)) { + Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions, + D.getIdentifier()->getName()); + return TypeRef(); + } else if (RecordType *EltTy = dyn_cast(CanonicalT)) { + // If the element type is a struct or union that contains a variadic + // array, reject it: C99 6.7.2.1p2. if (EltTy->getDecl()->hasFlexibleArrayMember()) { std::string Name; T->getAsString(Name); Diag(DeclType.Loc, diag::err_flexible_array_in_array, Name); return TypeRef(); } - } else if (isa(CanonicalT)) {// reject "void aryOfFunc[3]()" - Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions, - D.getIdentifier()->getName()); - } else if (CanonicalT->isVoidType()) { // reject "void aryOfVoids[3]" - Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_voids, - D.getIdentifier()->getName()); } - T = Context.getArrayType(T, ASM, ATI.TypeQuals, static_cast(ATI.NumElts)); break; diff --git a/clang/Sema/SemaType.cpp b/clang/Sema/SemaType.cpp index b0ed8c23b72b..153686e3455f 100644 --- a/clang/Sema/SemaType.cpp +++ b/clang/Sema/SemaType.cpp @@ -133,23 +133,26 @@ TypeRef Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { Type *CanonicalT = T->getCanonicalType(); - // If the element type is a struct or union that contains a variadic - // array, reject it: C99 6.7.2.1p2. - if (RecordType *EltTy = dyn_cast(CanonicalT)) { + // C99 6.7.5.2p1: If the element type is an incomplete or function type, + // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) + if (T->isIncompleteType()) { + Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type, + D.getIdentifier()->getName()); + return TypeRef(); + } else if (isa(CanonicalT)) { + Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions, + D.getIdentifier()->getName()); + return TypeRef(); + } else if (RecordType *EltTy = dyn_cast(CanonicalT)) { + // If the element type is a struct or union that contains a variadic + // array, reject it: C99 6.7.2.1p2. if (EltTy->getDecl()->hasFlexibleArrayMember()) { std::string Name; T->getAsString(Name); Diag(DeclType.Loc, diag::err_flexible_array_in_array, Name); return TypeRef(); } - } else if (isa(CanonicalT)) {// reject "void aryOfFunc[3]()" - Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions, - D.getIdentifier()->getName()); - } else if (CanonicalT->isVoidType()) { // reject "void aryOfVoids[3]" - Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_voids, - D.getIdentifier()->getName()); } - T = Context.getArrayType(T, ASM, ATI.TypeQuals, static_cast(ATI.NumElts)); break; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 0488eb069819..bb4182dbf9e9 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -464,8 +464,8 @@ DIAG(err_flexible_array_in_array, ERROR, "'%s' may not be used as an array element due to flexible array member") DIAG(err_illegal_decl_array_of_functions, ERROR, "'%s' declared as array of functions") -DIAG(err_illegal_decl_array_of_voids, ERROR, - "'%s' declared as array of voids") +DIAG(err_illegal_decl_array_incomplete_type, ERROR, + "array type for '%s' has incomplete element type") // Expressions. DIAG(ext_sizeof_function_type, EXTENSION,