update to CXXFunctionalCastExpr to support ir-gen for

type convesions of class objects [class.conv]. WIP.

llvm-svn: 80127
This commit is contained in:
Fariborz Jahanian 2009-08-26 18:55:36 +00:00
parent 13789b3af2
commit 1cec0c4c94
6 changed files with 47 additions and 21 deletions

View File

@ -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; }

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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<ParenListExpr>(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();

View File

@ -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<RecordType>()) {