зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
cfcd7fd0de
Коммит
0aebc81e02
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче