diff options
author | Anders Carlsson <andersca@mac.com> | 2009-09-09 21:33:21 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-09-09 21:33:21 +0000 |
commit | e9766d559ba577ba8e21d450feaae88c606e0ba3 (patch) | |
tree | 1fa26363e225872ed31fc8298bb1ea66b7511b7a | |
parent | 572a0df0fcc077919258f4d9130ff1a9d5ad019d (diff) | |
download | bcm5719-llvm-e9766d559ba577ba8e21d450feaae88c606e0ba3.tar.gz bcm5719-llvm-e9766d559ba577ba8e21d450feaae88c606e0ba3.zip |
If a cast expression needs either a conversion function or a constructor to be called, generate implicit child expressions that call them.
llvm-svn: 81383
-rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 22 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 105 |
11 files changed, 132 insertions, 129 deletions
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 91b5fd27073..82909144169 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -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; } diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index e311912d95f..9963a9b048b 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -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'"); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 969b789d517..dde6899c29b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -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. diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 8bda0f3e36e..2e7e8686169 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -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()) && diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index b4ce838af35..aecf9558636 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -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()); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index be2406d063b..05f94371cb2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -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. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 0fac947efe1..07804a93963 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -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); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index a73a2b912cc..68dd12e44eb 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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, diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index ac85b79b390..0ae5d343cad 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c2a4119c53e..723d6d7dfad 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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)); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 3943ce103ea..7fc754ffd52 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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) |