diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 105 |
4 files changed, 122 insertions, 57 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index a73a2b912c..68dd12e44e 100644 --- a/lib/Sema/Sema.h +++ b/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/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index ac85b79b39..0ae5d343ca 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c2a4119c53..723d6d7dfa 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3943ce103e..7fc754ffd5 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/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) |