forked from OSchip/llvm-project
update to CXXFunctionalCastExpr to support ir-gen for
type convesions of class objects [class.conv]. WIP. llvm-svn: 80127
This commit is contained in:
parent
13789b3af2
commit
1cec0c4c94
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>()) {
|
||||
|
|
Loading…
Reference in New Issue