From 5fbd7e02647c0a9ba1e26753e8246691638ec355 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 19 Jul 2007 00:42:40 +0000 Subject: [PATCH] Fix a crasher that Neil reported: Sema::GetTypeForDeclarator should never return a null type. If there is an error parsing the type, pick a new type for error recovery purposes. llvm-svn: 40029 --- clang/Sema/SemaType.cpp | 27 +++++++++++---------------- clang/test/Sema/array-constraint.c | 11 +++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 clang/test/Sema/array-constraint.c diff --git a/clang/Sema/SemaType.cpp b/clang/Sema/SemaType.cpp index 388359a75301..5b1db6e39b6c 100644 --- a/clang/Sema/SemaType.cpp +++ b/clang/Sema/SemaType.cpp @@ -103,9 +103,6 @@ static QualType ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) { QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { QualType T = ConvertDeclSpecToType(D.getDeclSpec(), Context); - // If there was an error parsing declspecs, return a null type pointer. - if (T.isNull()) return T; - // Apply const/volatile/restrict qualifiers to T. T = T.getQualifiedType(D.getDeclSpec().getTypeQualifiers()); @@ -120,19 +117,19 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { // C++ 8.3.2p4: There shall be no ... pointers to references ... Diag(D.getIdentifierLoc(), diag::err_illegal_decl_pointer_to_reference, D.getIdentifier()->getName()); - return QualType(); + T = Context.IntTy; } // Apply the pointer typequals to the pointer object. T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals); break; case DeclaratorChunk::Reference: - if (isa(T.getCanonicalType().getTypePtr())) { + if (const ReferenceType *RT = T->isReferenceType()) { // C++ 8.3.2p4: There shall be no references to references ... Diag(D.getIdentifierLoc(), diag::err_illegal_decl_reference_to_reference, D.getIdentifier()->getName()); - return QualType(); + T = RT->getReferenceeType(); } T = Context.getReferenceType(T); @@ -146,31 +143,29 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { ASM = ArrayType::Static; else ASM = ArrayType::Normal; - - Type *CanonicalT = T.getCanonicalType().getTypePtr(); - + // 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, T.getAsString()); - return QualType(); - } else if (isa(CanonicalT)) { + T = Context.IntTy; + } else if (T->isFunctionType()) { Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions, D.getIdentifier()->getName()); - return QualType(); - } else if (isa(CanonicalT)) { + T = Context.getPointerType(T); + } else if (const ReferenceType *RT = T->isReferenceType()) { // C++ 8.3.2p4: There shall be no ... arrays of references ... Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_references, D.getIdentifier()->getName()); - return QualType(); - } else if (RecordType *EltTy = dyn_cast(CanonicalT)) { + T = RT->getReferenceeType(); + } else if (RecordType *EltTy =dyn_cast(T.getCanonicalType())){ // 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()) { Diag(DeclType.Loc, diag::err_flexible_array_in_array, T.getAsString()); - return QualType(); + T = Context.IntTy; } } T = Context.getArrayType(T, ASM, ATI.TypeQuals, diff --git a/clang/test/Sema/array-constraint.c b/clang/test/Sema/array-constraint.c new file mode 100644 index 000000000000..4b70bb9bb3a4 --- /dev/null +++ b/clang/test/Sema/array-constraint.c @@ -0,0 +1,11 @@ +// RUN: clang -parse-ast-check %s + +struct s; +struct s* t (struct s z[]) { // expected-error {{array has incomplete element type}} + return z; +} + +void *k (void l[2]) { // expected-error {{array has incomplete element type}} + return l; +} + -- GitLab