From 1cec0c4c946d73f52d076587ab6b012cddbb4872 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 26 Aug 2009 18:55:36 +0000 Subject: [PATCH] update to CXXFunctionalCastExpr to support ir-gen for type convesions of class objects [class.conv]. WIP. llvm-svn: 80127 --- clang/include/clang/AST/ExprCXX.h | 8 +++++++- clang/lib/Sema/Sema.h | 7 +++++-- clang/lib/Sema/SemaCXXCast.cpp | 31 ++++++++++++++++++++----------- clang/lib/Sema/SemaChecking.cpp | 4 +++- clang/lib/Sema/SemaExpr.cpp | 11 +++++++---- clang/lib/Sema/SemaExprCXX.cpp | 7 +++++-- 6 files changed, 47 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index c2efcd228f94..dfc32c7f97ca 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -22,6 +22,7 @@ namespace clang { class CXXConstructorDecl; class CXXDestructorDecl; + class CXXMethodDecl; class CXXTemporary; //===--------------------------------------------------------------------===// @@ -539,15 +540,20 @@ 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, SourceLocation rParenLoc) : + Expr *castExpr, CXXMethodDecl *typeConversionMethod, + SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, writtenTy), + TypeConversionMethod(typeConversionMethod), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + CXXMethodDecl *getTypeConversionMethod() const + { return TypeConversionMethod; } SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 822589dd500b..5b7a247e25a7 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -3369,7 +3369,9 @@ public: /// CheckCastTypes - Check type constraints for casting between types under /// C semantics, or forward to CXXCheckCStyleCast in C++. bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr, - CastExpr::CastKind &Kind, bool FunctionalStyle = false); + CastExpr::CastKind &Kind, + CXXMethodDecl *& ConversionDecl, + bool FunctionalStyle = false); // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. @@ -3387,7 +3389,8 @@ public: /// CXXCheckCStyleCast - Check constraints of a C-style or function-style /// cast under C++ semantics. bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, - CastExpr::CastKind &Kind, bool FunctionalStyle); + CastExpr::CastKind &Kind, bool FunctionalStyle, + CXXMethodDecl *&ConversionDecl); /// CheckMessageArgumentTypes - Check types in an Obj-C message send. /// \param Method - May be null. diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 10da0945f433..2dee71308b0a 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -84,11 +84,13 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg); + unsigned &msg, + CXXMethodDecl *&ConversionDecl); static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, - CastExpr::CastKind &Kind, unsigned &msg); + CastExpr::CastKind &Kind, unsigned &msg, + CXXMethodDecl *&ConversionDecl); static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, unsigned &msg); static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, @@ -370,8 +372,10 @@ 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, OpRange, - Kind, msg) + Kind, msg, + ConversionDecl) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Static << SrcExpr->getType() << DestType << OpRange; @@ -383,7 +387,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, - CastExpr::CastKind &Kind, unsigned &msg) + CastExpr::CastKind &Kind, unsigned &msg, + CXXMethodDecl *&ConversionDecl) { // The order the tests is not entirely arbitrary. There is one conversion // that can be handled in two different ways. Given: @@ -417,7 +422,8 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, // C++ 5.2.9p2: An expression e can be explicitly converted to a type T // [...] if the declaration "T t(e);" is well-formed, [...]. - tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg); + tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg, + ConversionDecl); if (tcr != TC_NotApplicable) return tcr; @@ -746,7 +752,8 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, /// @c static_cast if the declaration "T t(e);" is well-formed [...]. TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, - bool CStyle, const SourceRange &OpRange, unsigned &msg) + bool CStyle, const SourceRange &OpRange, unsigned &msg, + CXXMethodDecl *&ConversionDecl) { if (DestType->isReferenceType()) { // At this point of CheckStaticCast, if the destination is a reference, @@ -767,9 +774,9 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, if (DestType->isRecordType()) { // There are no further possibilities for the target type being a class, // neither in static_cast nor in a C-style cast. So we can fail here. - // FIXME: We need to store this constructor in the AST. - if (Self.PerformInitializationByConstructor(DestType, &SrcExpr, 1, - OpRange.getBegin(), OpRange, DeclarationName(), Sema::IK_Direct)) + if ((ConversionDecl = + Self.PerformInitializationByConstructor(DestType, &SrcExpr, 1, + OpRange.getBegin(), OpRange, DeclarationName(), Sema::IK_Direct))) return TC_Success; // The function already emitted an error. msg = 0; @@ -1008,7 +1015,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, } bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, - CastExpr::CastKind &Kind, bool FunctionalStyle) + CastExpr::CastKind &Kind, bool FunctionalStyle, + 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. @@ -1038,7 +1046,8 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,msg); if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... - tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, Kind, msg); + tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, Kind, msg, + ConversionDecl); if (tcr == TC_NotApplicable) { // ... and finally a reinterpret_cast, ignoring const. tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5499e6cb4ed5..27f03bd98f49 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -390,7 +390,9 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { // GCC does an implicit conversion to the pointer or integer ValType. This // can fail in some cases (1i -> int**), check for this error case now. CastExpr::CastKind Kind = CastExpr::CK_Unknown; - if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind)) + CXXMethodDecl *ConversionDecl = 0; + if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, + ConversionDecl)) return true; // Okay, we have something that *can* be converted to the right type. Check diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 213292e159b0..7a8189835fbb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2902,9 +2902,12 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, /// CheckCastTypes - Check type constraints for casting between types. bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, - CastExpr::CastKind& Kind, bool FunctionalStyle) { + CastExpr::CastKind& Kind, + CXXMethodDecl *& ConversionDecl, + bool FunctionalStyle) { if (getLangOptions().CPlusPlus) - return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle); + return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle, + ConversionDecl); DefaultFunctionArrayConversion(castExpr); @@ -3031,9 +3034,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty, // If the Expr being casted is a ParenListExpr, handle it specially. if (isa(castExpr)) return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),castType); - + CXXMethodDecl *ConversionDecl = 0; if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr, - Kind)) + Kind, ConversionDecl)) return ExprError(); Op.release(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 669705b0d4c6..cf52bae86ca5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -210,12 +210,15 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, // if (NumExprs == 1) { CastExpr::CastKind Kind = CastExpr::CK_Unknown; - if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, /*functional-style*/true)) + CXXMethodDecl *ConversionDecl = 0; + if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, ConversionDecl, + /*functional-style*/true)) return ExprError(); exprs.release(); return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(), Ty, TyBeginLoc, Kind, - Exprs[0], RParenLoc)); + Exprs[0], ConversionDecl, + RParenLoc)); } if (const RecordType *RT = Ty->getAs()) {