/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.: /// @code new (memory) int[size][4] @endcode /// or /// @code ::new Foo(23, "hello") @endcode /// For the interpretation of this heap of arguments, consult the base version. Action::OwningExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, bool ParenTypeId, Declarator &D, SourceLocation ConstructorLParen, MultiExprArg ConstructorArgs, SourceLocation ConstructorRParen) { 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 ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new) << D.getSourceRange()); if (!Chunk.Arr.NumElts) return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) << D.getSourceRange()); ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); Skip = 1; } QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip); if (D.getInvalidType()) return ExprError(); if (CheckAllocatedType(AllocType, D)) return ExprError(); QualType ResultType = AllocType->isDependentType() ? Context.DependentTy : 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." if (ArraySize && !ArraySize->isTypeDependent()) { QualType SizeType = ArraySize->getType(); if (!SizeType->isIntegralType() && !SizeType->isEnumeralType()) return ExprError(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. if (!ArraySize->isValueDependent()) { llvm::APSInt Value; if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) { if (Value < llvm::APSInt( llvm::APInt::getNullValue(Value.getBitWidth()), false)) return ExprError(Diag(ArraySize->getSourceRange().getBegin(), diag::err_typecheck_negative_array_size) << ArraySize->getSourceRange()); } } } FunctionDecl *OperatorNew = 0; FunctionDecl *OperatorDelete = 0; Expr **PlaceArgs = (Expr**)PlacementArgs.get(); unsigned NumPlaceArgs = PlacementArgs.size(); if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) && FindAllocationFunctions(StartLoc, SourceRange(PlacementLParen, PlacementRParen), UseGlobal, AllocType, ArraySize, PlaceArgs, NumPlaceArgs, OperatorNew, OperatorDelete)) return ExprError(); bool Init = ConstructorLParen.isValid(); // --- Choosing a constructor --- // C++ 5.3.4p15 // 1) If T is a POD and there's no initializer (ConstructorLParen is invalid) // the object is not initialized. If the object, or any part of it, is // const-qualified, it's an error. // 2) If T is a POD and there's an empty initializer, the object is value- // initialized. // 3) If T is a POD and there's one initializer argument, the object is copy- // constructed. // 4) If T is a POD and there's more initializer arguments, it's an error. // 5) If T is not a POD, the initializer arguments are used as constructor // arguments. // // Or by the C++0x formulation: // 1) If there's no initializer, the object is default-initialized according // to C++0x rules. // 2) Otherwise, the object is direct-initialized. CXXConstructorDecl *Constructor = 0; Expr **ConsArgs = (Expr**)ConstructorArgs.get(); unsigned NumConsArgs = ConstructorArgs.size(); if (AllocType->isDependentType()) { // Skip all the checks. } // FIXME: Should check for primitive/aggregate here, not record. else 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( AllocType, ConsArgs, NumConsArgs, D.getSourceRange().getBegin(), SourceRange(D.getSourceRange().getBegin(), ConstructorRParen), RT->getDecl()->getDeclName(), NumConsArgs != 0 ? IK_Direct : IK_Default); if (!Constructor) return ExprError(); } else { if (!Init) { // FIXME: Check that no subpart is const. if (AllocType.isConstQualified()) return ExprError(Diag(StartLoc, diag::err_new_uninitialized_const) << D.getSourceRange()); } else if (NumConsArgs == 0) { // Object is value-initialized. Do nothing. } else if (NumConsArgs == 1) { // Object is direct-initialized. // FIXME: WHAT DeclarationName do we pass in here? if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc, DeclarationName() /*AllocType.getAsString()*/, /*DirectInit=*/true)) return ExprError(); } else { return ExprError(Diag(StartLoc, diag::err_builtin_direct_init_more_than_one_arg) << SourceRange(ConstructorLParen, ConstructorRParen)); } } // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16) PlacementArgs.release(); ConstructorArgs.release(); return Owned(new (Context) CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs, NumPlaceArgs, ParenTypeId, ArraySize, Constructor, Init, ConsArgs, NumConsArgs, OperatorDelete, ResultType, StartLoc, Init ? ConstructorRParen : SourceLocation())); }
/// ActOnCXXTypeConstructExpr - Parse construction of a specified type. /// Can be interpreted either as function-style casting ("int(x)") /// or class type construction ("ClassType(x,y,z)") /// or creation of a value-initialized type ("int()"). Action::OwningExprResult Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, SourceLocation LParenLoc, MultiExprArg exprs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { assert(TypeRep && "Missing type!"); QualType Ty = QualType::getFromOpaquePtr(TypeRep); unsigned NumExprs = exprs.size(); Expr **Exprs = (Expr**)exprs.get(); SourceLocation TyBeginLoc = TypeRange.getBegin(); SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc); if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) { exprs.release(); return Owned(new (Context) CXXTemporaryObjectExpr(0, Ty, TyBeginLoc, Exprs, NumExprs, RParenLoc)); } // C++ [expr.type.conv]p1: // If the expression list is a single expression, the type conversion // expression is equivalent (in definedness, and if defined in meaning) to the // corresponding cast expression. // if (NumExprs == 1) { if (CheckCastTypes(TypeRange, Ty, Exprs[0])) return ExprError(); exprs.release(); return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(), Ty, TyBeginLoc, Exprs[0], RParenLoc)); } if (const RecordType *RT = Ty->getAsRecordType()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); if (NumExprs > 1 || Record->hasUserDeclaredConstructor()) { CXXConstructorDecl *Constructor = PerformInitializationByConstructor(Ty, Exprs, NumExprs, TypeRange.getBegin(), SourceRange(TypeRange.getBegin(), RParenLoc), DeclarationName(), IK_Direct); if (!Constructor) return ExprError(); exprs.release(); return Owned(new (Context) CXXTemporaryObjectExpr(Constructor, Ty, TyBeginLoc, Exprs, NumExprs, RParenLoc)); } // Fall through to value-initialize an object of class type that // doesn't have a user-declared default constructor. } // C++ [expr.type.conv]p1: // If the expression list specifies more than a single value, the type shall // be a class with a suitably declared constructor. // if (NumExprs > 1) return ExprError(Diag(CommaLocs[0], diag::err_builtin_func_cast_more_than_one_arg) << FullRange); assert(NumExprs == 0 && "Expected 0 expressions"); // C++ [expr.type.conv]p2: // The expression T(), where T is a simple-type-specifier for a non-array // complete object type or the (possibly cv-qualified) void type, creates an // rvalue of the specified type, which is value-initialized. // if (Ty->isArrayType()) return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_array_type) << FullRange); if (!Ty->isDependentType() && !Ty->isVoidType() && RequireCompleteType(TyBeginLoc, Ty, diag::err_invalid_incomplete_type_use, FullRange)) return ExprError(); if (RequireNonAbstractType(TyBeginLoc, Ty, diag::err_allocation_of_abstract_type)) return ExprError(); exprs.release(); return Owned(new (Context) CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc)); }