If a cast expression needs either a conversion function or a constructor to be called, generate implicit child expressions that call them.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81383 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anders Carlsson 2009-09-09 21:33:21 +00:00
Родитель cfcd7fd0de
Коммит 0aebc81e02
11 изменённых файлов: 132 добавлений и 129 удалений

Просмотреть файл

@ -550,20 +550,16 @@ public:
/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c
/// x = int(0.5);
class CXXFunctionalCastExpr : public ExplicitCastExpr {
CXXMethodDecl *TypeConversionMethod;
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
Expr *castExpr, CXXMethodDecl *typeConversionMethod,
SourceLocation rParenLoc) :
ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, writtenTy),
TypeConversionMethod(typeConversionMethod),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
Expr *castExpr, SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
CXXMethodDecl *getTypeConversionMethod() const
{ return TypeConversionMethod; }
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }

Просмотреть файл

@ -264,28 +264,6 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
E->arg_begin() + 1, E->arg_end());
}
RValue
CodeGenFunction::EmitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *E) {
assert((E->getCastKind() == CastExpr::CK_UserDefinedConversion) &&
"EmitCXXFunctionalCastExpr - called with wrong cast");
CXXMethodDecl *MD = E->getTypeConversionMethod();
assert(MD && "EmitCXXFunctionalCastExpr - null conversion method");
assert(isa<CXXConversionDecl>(MD) && "EmitCXXFunctionalCastExpr - not"
" method decl");
const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
const llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
FPT->isVariadic());
llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
llvm::Value *This = EmitLValue(E->getSubExpr()).getAddress();
RValue RV = EmitCXXMemberCall(MD, Callee, This, 0, 0);
if (RV.isAggregate())
RV = RValue::get(RV.getAggregateAddr());
return RV;
}
llvm::Value *CodeGenFunction::LoadCXXThis() {
assert(isa<CXXMethodDecl>(CurFuncDecl) &&
"Must be in a C++ member function decl to load 'this'");

Просмотреть файл

@ -1158,19 +1158,11 @@ LValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator* E) {
/// all the reasons that casts are permitted with aggregate result, including
/// noop aggregate casts, and cast from scalar to union.
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
if (E->getCastKind() == CastExpr::CK_UserDefinedConversion) {
if (const CXXFunctionalCastExpr *CXXFExpr =
dyn_cast<CXXFunctionalCastExpr>(E))
return LValue::MakeAddr(
EmitCXXFunctionalCastExpr(CXXFExpr).getScalarVal(), 0);
assert(isa<CStyleCastExpr>(E) &&
"EmitCastLValue - Expected CStyleCastExpr");
return EmitLValue(E->getSubExpr());
}
// If this is an aggregate-to-aggregate cast, just use the input's address as
// the lvalue.
if (E->getCastKind() == CastExpr::CK_NoOp)
if (E->getCastKind() == CastExpr::CK_NoOp ||
E->getCastKind() == CastExpr::CK_ConstructorConversion ||
E->getCastKind() == CastExpr::CK_UserDefinedConversion)
return EmitLValue(E->getSubExpr());
// If this is an lvalue cast, treat it as a no-op.

Просмотреть файл

@ -184,19 +184,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
LValue::MakeAddr(CastPtr, 0));
return;
}
if (E->getCastKind() == CastExpr::CK_UserDefinedConversion) {
if (const CXXFunctionalCastExpr *CXXFExpr =
dyn_cast<CXXFunctionalCastExpr>(E))
CGF.EmitCXXFunctionalCastExpr(CXXFExpr);
else
if (isa<CStyleCastExpr>(E))
Visit(E->getSubExpr());
return;
}
// FIXME: Remove the CK_Unknown check here.
assert((E->getCastKind() == CastExpr::CK_NoOp ||
E->getCastKind() == CastExpr::CK_Unknown) &&
E->getCastKind() == CastExpr::CK_Unknown ||
E->getCastKind() == CastExpr::CK_UserDefinedConversion ||
E->getCastKind() == CastExpr::CK_ConstructorConversion) &&
"Only no-op casts allowed!");
assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(),
E->getType()) &&

Просмотреть файл

@ -227,14 +227,6 @@ public:
return llvm::Constant::getNullValue(ConvertType(E->getType()));
}
Value *VisitCastExpr(const CastExpr *E) {
if (E->getCastKind() == CastExpr::CK_UserDefinedConversion) {
if (const CXXFunctionalCastExpr *CXXFExpr =
dyn_cast<CXXFunctionalCastExpr>(E))
return CGF.EmitCXXFunctionalCastExpr(CXXFExpr).getScalarVal();
assert(isa<CStyleCastExpr>(E) &&
"VisitCastExpr - missing CStyleCastExpr");
}
// Make sure to evaluate VLA bounds now so that we have them for later.
if (E->getType()->isVariablyModifiedType())
CGF.EmitVLASize(E->getType());

Просмотреть файл

@ -324,17 +324,6 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *FalseBlock) {
if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond))
return EmitBranchOnBoolExpr(PE->getSubExpr(), TrueBlock, FalseBlock);
if (const CastExpr *E = dyn_cast<CastExpr>(Cond))
if (E->getCastKind() == CastExpr::CK_UserDefinedConversion) {
if (const CXXFunctionalCastExpr *CXXFExpr =
dyn_cast<CXXFunctionalCastExpr>(E)) {
EmitCXXFunctionalCastExpr(CXXFExpr);
return;
}
else if (isa<CStyleCastExpr>(E))
return EmitBranchOnBoolExpr(E->getSubExpr(), TrueBlock, FalseBlock);
assert(false && "EmitBranchOnBoolExpr - Expected CStyleCastExpr");
}
if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
// Handle X && Y in a condition.

Просмотреть файл

@ -841,8 +841,6 @@ public:
RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
const CXXMethodDecl *MD);
RValue EmitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *E);
RValue EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E);

Просмотреть файл

@ -1834,6 +1834,12 @@ public:
MultiExprArg Args,
SourceLocation rParenLoc);
OwningExprResult BuildCXXCastArgument(SourceLocation CastLoc,
QualType Ty,
CastExpr::CastKind Kind,
CXXMethodDecl *Method,
ExprArg Arg);
/// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
/// the default expr if needed.
OwningExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,

Просмотреть файл

@ -44,7 +44,8 @@ static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &DestRange);
static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
CastExpr::CastKind &Kind);
CastExpr::CastKind &Kind,
CXXMethodDecl *&ConversionDecl);
static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange,
@ -143,8 +144,22 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
case tok::kw_static_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
if (!TypeDependent)
CheckStaticCast(*this, Ex, DestType, OpRange, Kind);
if (!TypeDependent) {
CXXMethodDecl *Method = 0;
CheckStaticCast(*this, Ex, DestType, OpRange, Kind, Method);
if (Method) {
OwningExprResult CastArg
= BuildCXXCastArgument(OpLoc, DestType.getNonReferenceType(),
Kind, Method, Owned(Ex));
if (CastArg.isInvalid())
return ExprError();
Ex = CastArg.takeAs<Expr>();
}
}
return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(),
Kind, Ex, DestType, OpLoc));
}
@ -359,7 +374,8 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// implicit conversions explicit and getting rid of data loss warnings.
void
CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange, CastExpr::CastKind &Kind) {
const SourceRange &OpRange, CastExpr::CastKind &Kind,
CXXMethodDecl *&ConversionDecl) {
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@ -371,7 +387,6 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
Self.DefaultFunctionArrayConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
CXXMethodDecl *ConversionDecl = 0;
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, Kind,
OpRange, msg, ConversionDecl)
!= TC_Success && msg != 0)
@ -421,9 +436,16 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
// [...] if the declaration "T t(e);" is well-formed, [...].
tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg,
ConversionDecl);
if (tcr != TC_NotApplicable)
if (tcr != TC_NotApplicable) {
if (ConversionDecl) {
if (isa<CXXConstructorDecl>(ConversionDecl))
Kind = CastExpr::CK_ConstructorConversion;
else if (isa<CXXConversionDecl>(ConversionDecl))
Kind = CastExpr::CK_UserDefinedConversion;
}
return tcr;
}
// C++ 5.2.9p6: May apply the reverse of any standard conversion, except
// lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean
// conversions, subject to further restrictions.
@ -787,10 +809,12 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType,
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion)
if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion) {
if (CXXMethodDecl *MD =
dyn_cast<CXXMethodDecl>(ICS.UserDefined.ConversionFunction))
ConversionDecl = MD;
}
return ICS.ConversionKind == ImplicitConversionSequence::BadConversion ?
TC_NotApplicable : TC_Success;
}

Просмотреть файл

@ -3171,25 +3171,23 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty,
// If the Expr being casted is a ParenListExpr, handle it specially.
if (isa<ParenListExpr>(castExpr))
return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),castType);
CXXMethodDecl *ConversionDecl = 0;
CXXMethodDecl *Method = 0;
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr,
Kind, ConversionDecl))
Kind, Method))
return ExprError();
if (ConversionDecl) {
// encounterred a c-style cast requiring a conversion function.
if (CXXConversionDecl *CD = dyn_cast<CXXConversionDecl>(ConversionDecl)) {
castExpr =
new (Context) CXXFunctionalCastExpr(castType.getNonReferenceType(),
castType, LParenLoc,
CastExpr::CK_UserDefinedConversion,
castExpr, CD,
RParenLoc);
Kind = CastExpr::CK_UserDefinedConversion;
}
// FIXME. AST for when dealing with conversion functions (FunctionDecl).
if (Method) {
OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, castType, Kind,
Method, move(Op));
if (CastArg.isInvalid())
return ExprError();
castExpr = CastArg.takeAs<Expr>();
} else {
Op.release();
}
Op.release();
return Owned(new (Context) CStyleCastExpr(castType.getNonReferenceType(),
Kind, castExpr, castType,
LParenLoc, RParenLoc));

Просмотреть файл

@ -224,19 +224,25 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
//
if (NumExprs == 1) {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
CXXMethodDecl *ConversionDecl = 0;
if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, ConversionDecl,
/*functional-style*/true))
CXXMethodDecl *Method = 0;
if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, Method,
/*FunctionalStyle=*/true))
return ExprError();
// We done't build this AST for X(i) where we are constructing an object.
if (!ConversionDecl || !isa<CXXConstructorDecl>(ConversionDecl)) {
exprs.release();
return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
Ty, TyBeginLoc,
CastExpr::CK_UserDefinedConversion,
Exprs[0], ConversionDecl,
RParenLoc));
exprs.release();
if (Method) {
OwningExprResult CastArg
= BuildCXXCastArgument(TypeRange.getBegin(), Ty.getNonReferenceType(),
Kind, Method, Owned(Exprs[0]));
if (CastArg.isInvalid())
return ExprError();
Exprs[0] = CastArg.takeAs<Expr>();
}
return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
Ty, TyBeginLoc, Kind,
Exprs[0], RParenLoc));
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@ -919,30 +925,25 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
{
FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
if (CXXConversionDecl *CV = dyn_cast<CXXConversionDecl>(FD)) {
// FIXME. Get actual Source Location.
From =
new (Context) CXXFunctionalCastExpr(ToType.getNonReferenceType(),
ToType, SourceLocation(),
CastExpr::CK_UserDefinedConversion,
From, CV,
SourceLocation());
if (isa<CXXConversionDecl>(FD))
CastKind = CastExpr::CK_UserDefinedConversion;
}
else if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
// FIXME. Do we need to check for isLValueReferenceType?
DefaultFunctionArrayConversion(From);
OwningExprResult InitResult =
BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
ToType.getNonReferenceType(), CD,
MultiExprArg(*this, (void**)&From, 1));
// Take ownership of this expression.
From = InitResult.takeAs<Expr>();
CastKind = CastExpr::CK_ConstructorConversion ;
}
ImpCastExprToType(From, ToType.getNonReferenceType(),
CastKind,
ToType->isLValueReferenceType());
else if (isa<CXXConstructorDecl>(FD))
CastKind = CastExpr::CK_ConstructorConversion;
else
assert(0 && "Unknown conversion function kind!");
OwningExprResult CastArg
= BuildCXXCastArgument(From->getLocStart(),
ToType.getNonReferenceType(),
CastKind, cast<CXXMethodDecl>(FD),
Owned(From));
if (CastArg.isInvalid())
return true;
From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(),
CastKind, CastArg.takeAs<Expr>(),
ToType->isLValueReferenceType());
return false;
}
@ -1889,6 +1890,42 @@ Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
ConvName, DeclPtrTy(), SS);
}
Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
QualType Ty,
CastExpr::CastKind Kind,
CXXMethodDecl *Method,
ExprArg Arg) {
Expr *From = Arg.takeAs<Expr>();
switch (Kind) {
default: assert(0 && "Unhandled cast kind!");
case CastExpr::CK_ConstructorConversion: {
DefaultFunctionArrayConversion(From);
return BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
MultiExprArg(*this, (void **)&From, 1));
}
case CastExpr::CK_UserDefinedConversion: {
// Create an implicit member expr to refer to the conversion operator.
MemberExpr *ME =
new (Context) MemberExpr(From, From->getType()->isPointerType(), Method,
SourceLocation(), Method->getType());
// And an implicit call expr that calls it.
QualType ResultType = Method->getResultType().getNonReferenceType();
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, 0, 0,
ResultType,
SourceLocation());
return Owned(CE);
}
}
}
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)