diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-24 19:52:54 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-24 19:52:54 +0000 |
commit | e7450f5dbd5bed63b8ef9db86350a8fc3db011e8 (patch) | |
tree | 61d7b8565db05760fb505fa9c25af4ed13e48bbf /lib/Sema | |
parent | 6256d3654533547a7996170647c21a859cb441e1 (diff) |
Make sure to use RequireCompleteType rather than testing for
incomplete types. RequireCompleteType is needed when the type may be
completed by instantiating a template.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67643 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 65 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 171 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 41 |
3 files changed, 152 insertions, 125 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a3b60047d6..b76126aa8f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -881,6 +881,8 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { // C99 6.7.5.3p4: the parameters in a parameter type list in a // function declarator that is part of a function definition of // that function shall not have incomplete type. + // + // This is also C++ [dcl.fct]p6. if (!Param->isInvalidDecl() && RequireCompleteType(Param->getLocation(), Param->getType(), diag::err_typecheck_decl_incomplete_type)) { @@ -2723,12 +2725,12 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) { } // The return type of a function definition must be complete - // (C99 6.9.1p3) - if (FD->getResultType()->isIncompleteType() && - !FD->getResultType()->isVoidType()) { - Diag(FD->getLocation(), diag::err_func_def_incomplete_result) << FD; + // (C99 6.9.1p3, C++ [dcl.fct]p6). + QualType ResultType = FD->getResultType(); + if (!ResultType->isDependentType() && !ResultType->isVoidType() && + RequireCompleteType(FD->getLocation(), ResultType, + diag::err_func_def_incomplete_result)) FD->setInvalidDecl(); - } PushDeclContext(FnBodyScope, FD); @@ -3726,33 +3728,27 @@ void Sema::ActOnFields(Scope* S, if (FD->isInvalidDecl()) continue; - // C99 6.7.2.1p2 - A field may not be a function type. + // C99 6.7.2.1p2: + // A structure or union shall not contain a member with + // incomplete or function type (hence, a structure shall not + // contain an instance of itself, but may contain a pointer to + // an instance of itself), except that the last member of a + // structure with more than one named member may have incomplete + // array type; such a structure (and any union containing, + // possibly recursively, a member that is such a structure) + // shall not be a member of a structure or an element of an + // array. if (FDTy->isFunctionType()) { + // Field declared as a function. Diag(FD->getLocation(), diag::err_field_declared_as_function) << FD->getDeclName(); FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; - } - // C99 6.7.2.1p2 - A field may not be an incomplete type except... - if (FDTy->isIncompleteType()) { - if (!Record) { // Incomplete ivar type is always an error. - RequireCompleteType(FD->getLocation(), FD->getType(), - diag::err_field_incomplete); - FD->setInvalidDecl(); - EnclosingDecl->setInvalidDecl(); - continue; - } - if (i != NumFields-1 || // ... that the last member ... - !Record->isStruct() || // ... of a structure ... - !FDTy->isArrayType()) { //... may have incomplete array type. - RequireCompleteType(FD->getLocation(), FD->getType(), - diag::err_field_incomplete); - FD->setInvalidDecl(); - EnclosingDecl->setInvalidDecl(); - continue; - } - if (NumNamedMembers < 1) { //... must have more than named member ... + } else if (FDTy->isIncompleteArrayType() && i == NumFields - 1 && + Record && Record->isStruct()) { + // Flexible array member. + if (NumNamedMembers < 1) { Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) << FD->getDeclName(); FD->setInvalidDecl(); @@ -3762,10 +3758,14 @@ void Sema::ActOnFields(Scope* S, // Okay, we have a legal flexible array member at the end of the struct. if (Record) Record->setHasFlexibleArrayMember(true); - } - /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the - /// field of another structure or the element of an array. - if (const RecordType *FDTTy = FDTy->getAsRecordType()) { + } else if (!FDTy->isDependentType() && + RequireCompleteType(FD->getLocation(), FD->getType(), + diag::err_field_incomplete)) { + // Incomplete type + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (const RecordType *FDTTy = FDTy->getAsRecordType()) { if (FDTTy->getDecl()->hasFlexibleArrayMember()) { // If this is a member of a union, then entire union becomes "flexible". if (Record && Record->isUnion()) { @@ -3787,9 +3787,8 @@ void Sema::ActOnFields(Scope* S, } } } - } - /// A field cannot be an Objective-c object - if (FDTy->isObjCInterfaceType()) { + } else if (FDTy->isObjCInterfaceType()) { + /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object); FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 2732a54e65..03d8501245 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1593,14 +1593,20 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, return ExprError(Diag(IndexExpr->getLocStart(), diag::err_typecheck_subscript) << IndexExpr->getSourceRange()); - // C99 6.5.2.1p1: "shall have type "pointer to *object* type". In practice, - // the following check catches trying to index a pointer to a function (e.g. - // void (*)(int)) and pointers to incomplete types. Functions are not - // objects in C99. - if (!ResultType->isObjectType() && !ResultType->isDependentType()) - return ExprError(Diag(BaseExpr->getLocStart(), - diag::err_typecheck_subscript_not_object) - << BaseExpr->getType() << BaseExpr->getSourceRange()); + // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, + // C++ [expr.sub]p1: The type "T" shall be a completely-defined object + // type. Note that Functions are not objects, and that (in C99 parlance) + // incomplete types are not object types. + if (ResultType->isFunctionType()) { + Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type) + << ResultType << BaseExpr->getSourceRange(); + return ExprError(); + } + if (!ResultType->isDependentType() && + RequireCompleteType(BaseExpr->getLocStart(), ResultType, + diag::err_subscript_incomplete_type, + BaseExpr->getSourceRange())) + return ExprError(); Base.release(); Idx.release(); @@ -3155,35 +3161,33 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 if (const PointerType* PTy = PExp->getType()->getAsPointerType()) { if (IExp->getType()->isIntegerType()) { // Check for arithmetic on pointers to incomplete types - if (!PTy->getPointeeType()->isObjectType()) { - if (PTy->getPointeeType()->isVoidType()) { - if (getLangOptions().CPlusPlus) { - Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); - return QualType(); - } - - // GNU extension: arithmetic on pointer to void - Diag(Loc, diag::ext_gnu_void_ptr) + if (PTy->getPointeeType()->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) << lex->getSourceRange() << rex->getSourceRange(); - } else if (PTy->getPointeeType()->isFunctionType()) { - if (getLangOptions().CPlusPlus) { - Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << lex->getType() << lex->getSourceRange(); - return QualType(); - } + return QualType(); + } - // GNU extension: arithmetic on pointer to function - Diag(Loc, diag::ext_gnu_ptr_func_arith) + // GNU extension: arithmetic on pointer to void + Diag(Loc, diag::ext_gnu_void_ptr) + << lex->getSourceRange() << rex->getSourceRange(); + } else if (PTy->getPointeeType()->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) << lex->getType() << lex->getSourceRange(); - } else { - RequireCompleteType(Loc, PTy->getPointeeType(), - diag::err_typecheck_arithmetic_incomplete_type, - lex->getSourceRange(), SourceRange(), - lex->getType()); return QualType(); } - } + + // GNU extension: arithmetic on pointer to function + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << lex->getType() << lex->getSourceRange(); + } else if (!PTy->isDependentType() && + RequireCompleteType(Loc, PTy->getPointeeType(), + diag::err_typecheck_arithmetic_incomplete_type, + lex->getSourceRange(), SourceRange(), + lex->getType())) + return QualType(); + return PExp->getType(); } } @@ -3209,61 +3213,80 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) { QualType lpointee = LHSPTy->getPointeeType(); - // The LHS must be an object type, not incomplete, function, etc. - if (!lpointee->isObjectType()) { - // Handle the GNU void* extension. - if (lpointee->isVoidType()) { - Diag(Loc, diag::ext_gnu_void_ptr) + // The LHS must be an completely-defined object type. + + bool ComplainAboutVoid = false; + Expr *ComplainAboutFunc = 0; + if (lpointee->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) << lex->getSourceRange() << rex->getSourceRange(); - } else if (lpointee->isFunctionType()) { - if (getLangOptions().CPlusPlus) { - Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << lex->getType() << lex->getSourceRange(); - return QualType(); - } + return QualType(); + } - // GNU extension: arithmetic on pointer to function - Diag(Loc, diag::ext_gnu_ptr_func_arith) - << lex->getType() << lex->getSourceRange(); - } else { - Diag(Loc, diag::err_typecheck_sub_ptr_object) + // GNU C extension: arithmetic on pointer to void + ComplainAboutVoid = true; + } else if (lpointee->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) << lex->getType() << lex->getSourceRange(); return QualType(); } - } + + // GNU C extension: arithmetic on pointer to function + ComplainAboutFunc = lex; + } else if (!lpointee->isDependentType() && + RequireCompleteType(Loc, lpointee, + diag::err_typecheck_sub_ptr_object, + lex->getSourceRange(), + SourceRange(), + lex->getType())) + return QualType(); // The result type of a pointer-int computation is the pointer type. - if (rex->getType()->isIntegerType()) + if (rex->getType()->isIntegerType()) { + if (ComplainAboutVoid) + Diag(Loc, diag::ext_gnu_void_ptr) + << lex->getSourceRange() << rex->getSourceRange(); + if (ComplainAboutFunc) + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << ComplainAboutFunc->getType() + << ComplainAboutFunc->getSourceRange(); + return lex->getType(); + } // Handle pointer-pointer subtractions. if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) { QualType rpointee = RHSPTy->getPointeeType(); - // RHS must be an object type, unless void (GNU). - if (!rpointee->isObjectType()) { - // Handle the GNU void* extension. - if (rpointee->isVoidType()) { - if (!lpointee->isVoidType()) - Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); - } else if (rpointee->isFunctionType()) { - if (getLangOptions().CPlusPlus) { - Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << rex->getType() << rex->getSourceRange(); - return QualType(); - } + // RHS must be a completely-type object type. + // Handle the GNU void* extension. + if (rpointee->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) + << lex->getSourceRange() << rex->getSourceRange(); + return QualType(); + } - // GNU extension: arithmetic on pointer to function - if (!lpointee->isFunctionType()) - Diag(Loc, diag::ext_gnu_ptr_func_arith) - << lex->getType() << lex->getSourceRange(); - } else { - Diag(Loc, diag::err_typecheck_sub_ptr_object) + ComplainAboutVoid = true; + } else if (rpointee->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) << rex->getType() << rex->getSourceRange(); return QualType(); } - } + + // GNU extension: arithmetic on pointer to function + if (!ComplainAboutFunc) + ComplainAboutFunc = rex; + } else if (!rpointee->isDependentType() && + RequireCompleteType(Loc, rpointee, + diag::err_typecheck_sub_ptr_object, + rex->getSourceRange(), + SourceRange(), + rex->getType())) + return QualType(); // Pointee types must be compatible. if (!Context.typesAreCompatible( @@ -3275,6 +3298,14 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, return QualType(); } + if (ComplainAboutVoid) + Diag(Loc, diag::ext_gnu_void_ptr) + << lex->getSourceRange() << rex->getSourceRange(); + if (ComplainAboutFunc) + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << ComplainAboutFunc->getType() + << ComplainAboutFunc->getSourceRange(); + return Context.getPointerDiffType(); } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 2abf87b23f..e2cda9dff9 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -242,10 +242,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (CheckAllocatedType(AllocType, D)) return ExprError(); - if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType, - diag::err_allocation_of_abstract_type)) - return ExprError(); - QualType ResultType = AllocType->isDependentType() ? Context.DependentTy : Context.getPointerType(AllocType); @@ -364,23 +360,20 @@ bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D) { // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an // abstract class type or array thereof. - // FIXME: We don't have abstract types yet. - // FIXME: Under C++ semantics, an incomplete object type is still an object - // type. This code assumes the C semantics, where it's not. - if (!AllocType->isObjectType()) { - unsigned type; // For the select in the message. - if (AllocType->isFunctionType()) { - type = 0; - } else if(AllocType->isIncompleteType()) { - type = 1; - } else { - assert(AllocType->isReferenceType() && "Unhandled non-object type."); - type = 2; - } - Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type) - << AllocType << type << D.getSourceRange(); + if (AllocType->isFunctionType()) + return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type) + << AllocType << 0 << D.getSourceRange(); + else if (AllocType->isReferenceType()) + return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type) + << AllocType << 1 << D.getSourceRange(); + else if (!AllocType->isDependentType() && + RequireCompleteType(D.getSourceRange().getBegin(), AllocType, + diag::err_new_incomplete_type, + D.getSourceRange())) + return true; + else if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType, + diag::err_allocation_of_abstract_type)) return true; - } // Every dimension shall be of constant size. unsigned i = 1; @@ -943,11 +936,15 @@ QualType Sema::CheckPointerToMemberOperands( // class type) [...] QualType RType = rex->getType(); const MemberPointerType *MemPtr = RType->getAsMemberPointerType(); - if (!MemPtr || MemPtr->getClass()->isIncompleteType()) { + if (!MemPtr) { Diag(Loc, diag::err_bad_memptr_rhs) << OpSpelling << RType << rex->getSourceRange(); return QualType(); - } + } else if (RequireCompleteType(Loc, QualType(MemPtr->getClass(), 0), + diag::err_memptr_rhs_incomplete, + rex->getSourceRange())) + return QualType(); + QualType Class(MemPtr->getClass(), 0); // C++ 5.5p2 |