diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-12-02 14:43:59 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-12-02 14:43:59 +0000 |
commit | cee63fbf0e64ac526582312bf8cf33263fc5c16e (patch) | |
tree | 274408c3fad7aaaaa463f5f50bce9f516ff3422b /lib/Sema/SemaExprCXX.cpp | |
parent | 04f9d468f7abfd8a1d85a2ef7cd9c48adb1efa58 (diff) |
Handle new by passing the Declaration to the Action, not a processed type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60413 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 108 |
1 files changed, 72 insertions, 36 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3633da89bc..bfc367dd58 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -180,30 +180,60 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, ExprTy **PlacementArgs, unsigned NumPlaceArgs, SourceLocation PlacementRParen, bool ParenTypeId, - SourceLocation TyStart, TypeTy *Ty, SourceLocation TyEnd, - SourceLocation ConstructorLParen, + Declarator &D, SourceLocation ConstructorLParen, ExprTy **ConstructorArgs, unsigned NumConsArgs, SourceLocation ConstructorRParen) { - QualType AllocType = QualType::getFromOpaquePtr(Ty); - QualType CheckType = AllocType; - // To leverage the existing parser as much as possible, array types are - // parsed as VLAs. Unwrap for checking. - if (const VariableArrayType *VLA = Context.getAsVariableArrayType(AllocType)) - CheckType = VLA->getElementType(); - - // Validate the type, and unwrap an array if any. - if (CheckAllocatedType(CheckType, StartLoc, SourceRange(TyStart, TyEnd))) + // FIXME: Throughout this function, we have rather bad location information. + // Implementing Declarator::getSourceRange() would go a long way toward + // fixing that. + + Expr *ArraySize = 0; + unsigned Skip = 0; + // If the specified type is an array, unwrap it and save the expression. + if (D.getNumTypeObjects() > 0 && + D.getTypeObject(0).Kind == DeclaratorChunk::Array) { + DeclaratorChunk &Chunk = D.getTypeObject(0); + if (Chunk.Arr.hasStatic) + return Diag(Chunk.Loc, diag::err_static_illegal_in_new); + if (!Chunk.Arr.NumElts) + return Diag(Chunk.Loc, diag::err_array_new_needs_size); + ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); + Skip = 1; + } + + QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip); + if (D.getInvalidType()) + return true; + + if (CheckAllocatedType(AllocType, D)) return true; - QualType ResultType = Context.getPointerType(CheckType); + QualType ResultType = Context.getPointerType(AllocType); // That every array dimension except the first is constant was already // checked by the type check above. + // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral // or enumeration type with a non-negative value." - // This was checked by ActOnTypeName, since C99 has the same restriction on - // VLA expressions. + if (ArraySize) { + QualType SizeType = ArraySize->getType(); + if (!SizeType->isIntegralType() && !SizeType->isEnumeralType()) + return Diag(ArraySize->getSourceRange().getBegin(), + diag::err_array_size_not_integral) + << SizeType << ArraySize->getSourceRange(); + // Let's see if this is a constant < 0. If so, we reject it out of hand. + // We don't care about special rules, so we tell the machinery it's not + // evaluated - it gives us a result in more cases. + llvm::APSInt Value; + if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) { + if (Value < llvm::APSInt( + llvm::APInt::getNullValue(Value.getBitWidth()), false)) + return Diag(ArraySize->getSourceRange().getBegin(), + diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange(); + } + } // --- Choosing an allocation function --- // C++ 5.3.4p8 - 14 & 18 @@ -239,12 +269,14 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, // 2) Otherwise, the object is direct-initialized. CXXConstructorDecl *Constructor = 0; Expr **ConsArgs = (Expr**)ConstructorArgs; - if (const RecordType *RT = CheckType->getAsRecordType()) { + if (const RecordType *RT = AllocType->getAsRecordType()) { // FIXME: This is incorrect for when there is an empty initializer and // no user-defined constructor. Must zero-initialize, not default-construct. Constructor = PerformInitializationByConstructor( - CheckType, ConsArgs, NumConsArgs, - TyStart, SourceRange(TyStart, ConstructorRParen), + AllocType, ConsArgs, NumConsArgs, + D.getDeclSpec().getSourceRange().getBegin(), + SourceRange(D.getDeclSpec().getSourceRange().getBegin(), + ConstructorRParen), RT->getDecl()->getDeclName(), NumConsArgs != 0 ? IK_Direct : IK_Default); if (!Constructor) @@ -252,9 +284,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, } else { if (!Init) { // FIXME: Check that no subpart is const. - if (CheckType.isConstQualified()) { + if (AllocType.isConstQualified()) { Diag(StartLoc, diag::err_new_uninitialized_const) - << SourceRange(StartLoc, TyEnd); + << D.getSourceRange(); return true; } } else if (NumConsArgs == 0) { @@ -262,8 +294,8 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, } else if (NumConsArgs == 1) { // Object is direct-initialized. // FIXME: WHAT DeclarationName do we pass in here? - if (CheckInitializerTypes(ConsArgs[0], CheckType, StartLoc, - DeclarationName() /*CheckType.getAsString()*/)) + if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc, + DeclarationName() /*AllocType.getAsString()*/)) return true; } else { Diag(StartLoc, diag::err_builtin_direct_init_more_than_one_arg) @@ -274,16 +306,15 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16) return new CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs, NumPlaceArgs, - ParenTypeId, AllocType, Constructor, Init, + ParenTypeId, ArraySize, Constructor, Init, ConsArgs, NumConsArgs, OperatorDelete, ResultType, - StartLoc, Init ? ConstructorRParen : TyEnd); + StartLoc, Init ? ConstructorRParen : SourceLocation()); } /// CheckAllocatedType - Checks that a type is suitable as the allocated type /// in a new-expression. /// dimension off and stores the size expression in ArraySize. -bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation StartLoc, - const SourceRange &TyR) +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. @@ -291,29 +322,34 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation StartLoc, // 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()) { - diag::kind msg; + unsigned type; // For the select in the message. if (AllocType->isFunctionType()) { - msg = diag::err_new_function; + type = 0; } else if(AllocType->isIncompleteType()) { - msg = diag::err_new_incomplete; - } else if(AllocType->isReferenceType()) { - msg = diag::err_new_reference; + type = 1; } else { - assert(false && "Unexpected type class"); - return true; + assert(AllocType->isReferenceType() && "What else could it be?"); + type = 2; } - Diag(StartLoc, msg) << AllocType << TyR; + SourceRange TyR = D.getDeclSpec().getSourceRange(); + // FIXME: This is very much a guess and won't work for, e.g., pointers. + if (D.getNumTypeObjects() > 0) + TyR.setEnd(D.getTypeObject(0).Loc); + Diag(TyR.getBegin(), diag::err_bad_new_type) + << AllocType.getAsString() << type << TyR; return true; } - // Every dimension beyond the first shall be of constant size. + // Every dimension shall be of constant size. + unsigned i = 1; while (const ArrayType *Array = Context.getAsArrayType(AllocType)) { if (!Array->isConstantArrayType()) { - // FIXME: Might be nice to get a better source range from somewhere. - Diag(StartLoc, diag::err_new_array_nonconst) << TyR; + Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst) + << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange(); return true; } AllocType = Array->getElementType(); + ++i; } return false; |