From 7f9e646b7ed47bc8e9a60031ad0c2b55031e2077 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 15 Sep 2009 04:48:33 +0000 Subject: [PATCH] Handle reinterpret_cast between integral types and pointer types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81837 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 8 +++++++- include/clang/AST/ExprCXX.h | 6 +++--- lib/AST/Expr.cpp | 4 ++++ lib/CodeGen/CGExprScalar.cpp | 16 ++++++++++++++++ lib/Sema/SemaCXXCast.cpp | 19 ++++++++++++------- test/CodeGenCXX/reinterpret-cast.cpp | 12 ++++++++++++ 6 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 test/CodeGenCXX/reinterpret-cast.cpp diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 81aecf7f31..3e122c1f53 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1368,7 +1368,13 @@ public: CK_UserDefinedConversion, /// CK_ConstructorConversion - Conversion by constructor - CK_ConstructorConversion + CK_ConstructorConversion, + + /// CK_IntegralToPointer - Integral to pointer + CK_IntegralToPointer, + + /// CK_PointerToIntegral - Pointer to integral + CK_PointerToIntegral }; struct CastInfo { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 871014d6c8..5e3dec7705 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -185,9 +185,9 @@ public: /// @c reinterpret_cast(VoidPtr). class CXXReinterpretCastExpr : public CXXNamedCastExpr { public: - CXXReinterpretCastExpr(QualType ty, Expr *op, QualType writtenTy, - SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, CK_BitCast, op, + CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, + QualType writtenTy, SourceLocation l) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, writtenTy, l) {} static bool classof(const Stmt *T) { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 620b5b8901..0ac896c783 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -422,6 +422,10 @@ const char *CastExpr::getCastKindName() const { return "UserDefinedConversion"; case CastExpr::CK_ConstructorConversion: return "ConstructorConversion"; + case CastExpr::CK_IntegralToPointer: + return "IntegralToPointer"; + case CastExpr::CK_PointerToIntegral: + return "PointerToIntegral"; } assert(0 && "Unhandled cast kind!"); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 7f9b66468b..682d14ca2e 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -625,6 +625,12 @@ Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy, switch (Kind) { default: + // FIXME: Assert here. + // assert(0 && "Unhandled cast kind!"); + break; + case CastExpr::CK_Unknown: + // FIXME: We should really assert here - Unknown casts should never get + // as far as to codegen. break; case CastExpr::CK_BitCast: { Value *Src = Visit(const_cast(E)); @@ -685,6 +691,16 @@ Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy, NullCheckValue); } + case CastExpr::CK_IntegralToPointer: { + Value *Src = Visit(const_cast(E)); + return Builder.CreateIntToPtr(Src, ConvertType(DestTy)); + } + + case CastExpr::CK_PointerToIntegral: { + Value *Src = Visit(const_cast(E)); + return Builder.CreatePtrToInt(Src, ConvertType(DestTy)); + } + } // Handle cases where the source is an non-complex type. diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 0ae5d343ca..dbd6c6fde5 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -41,7 +41,8 @@ static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &DestRange); static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, - const SourceRange &DestRange); + const SourceRange &DestRange, + CastExpr::CastKind &Kind); static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, CastExpr::CastKind &Kind, @@ -135,13 +136,14 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(), Kind, Ex, DestType, OpLoc)); } - case tok::kw_reinterpret_cast: + case tok::kw_reinterpret_cast: { + CastExpr::CastKind Kind = CastExpr::CK_Unknown; if (!TypeDependent) - CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange); + CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind); return Owned(new (Context) CXXReinterpretCastExpr( DestType.getNonReferenceType(), - Ex, DestType, OpLoc)); - + Kind, Ex, DestType, OpLoc)); + } case tok::kw_static_cast: { CastExpr::CastKind Kind = CastExpr::CK_Unknown; if (!TypeDependent) { @@ -355,11 +357,11 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// char *bytes = reinterpret_cast\(int_ptr); void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, const SourceRange &DestRange) { + const SourceRange &OpRange, const SourceRange &DestRange, + CastExpr::CastKind &Kind) { if (!DestType->isLValueReferenceType()) Self.DefaultFunctionArrayConversion(SrcExpr); - CastExpr::CastKind Kind = CastExpr::CK_Unknown; unsigned msg = diag::err_bad_cxx_cast_generic; if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, Kind, OpRange, msg) @@ -950,6 +952,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_reinterpret_cast_small_int; return TC_Failed; } + Kind = CastExpr::CK_PointerToIntegral; return TC_Success; } @@ -982,6 +985,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_reinterpret_cast_small_int; return TC_Failed; } + Kind = CastExpr::CK_PointerToIntegral; return TC_Success; } @@ -989,6 +993,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, assert(destIsPtr && "One type must be a pointer"); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. + Kind = CastExpr::CK_IntegralToPointer; return TC_Success; } diff --git a/test/CodeGenCXX/reinterpret-cast.cpp b/test/CodeGenCXX/reinterpret-cast.cpp new file mode 100644 index 0000000000..ae3ab2f8b0 --- /dev/null +++ b/test/CodeGenCXX/reinterpret-cast.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -emit-llvm -o - %s -std=c++0x +void *f1(unsigned long l) { + return reinterpret_cast(l); +} + +unsigned long f2() { + return reinterpret_cast(nullptr); +} + +unsigned long f3(void *p) { + return reinterpret_cast(p); +} \ No newline at end of file -- 2.40.0