/// 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)); }