From: John McCall Date: Sat, 13 Nov 2010 01:35:44 +0000 (+0000) Subject: Introduce a null-to-pointer implicit cast kind. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=404cd1669c3ba138a9ae0a619bd689cce5aae271;p=clang Introduce a null-to-pointer implicit cast kind. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118966 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d7e8fd8d90..be6e1bca58 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1982,6 +1982,7 @@ private: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToMemberPointer: + case CK_NullToPointer: case CK_UserDefinedConversion: case CK_ConstructorConversion: case CK_IntegralToPointer: diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 8b01490160..4e57df1af6 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -57,6 +57,9 @@ enum CastKind { /// CK_FunctionToPointerDecay - Function to pointer decay. CK_FunctionToPointerDecay, + /// CK_NullToPointer - Null pointer to pointer. + CK_NullToPointer, + /// CK_NullToMemberPointer - Null pointer to member pointer. CK_NullToMemberPointer, diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 7d05bdb264..2edf62ab39 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -764,6 +764,8 @@ const char *CastExpr::getCastKindName() const { return "FunctionToPointerDecay"; case CK_NullToMemberPointer: return "NullToMemberPointer"; + case CK_NullToPointer: + return "NullToPointer"; case CK_BaseToDerivedMemberPointer: return "BaseToDerivedMemberPointer"; case CK_DerivedToBaseMemberPointer: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 451aa2a253..dfeb32df3d 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -604,6 +604,12 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { return true; } + case CK_NullToPointer: { + Result.Base = 0; + Result.Offset = CharUnits::Zero(); + return true; + } + case CK_IntegralToPointer: { APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 1669a353a5..73b5bf8967 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -2518,6 +2518,7 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_BitCast: case CK_LValueBitCast: case CK_IntegralCast: + case CK_NullToPointer: case CK_IntegralToPointer: case CK_PointerToIntegral: case CK_IntegralToFloating: diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 355c18f79c..bb2eb3c798 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1806,6 +1806,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToMemberPointer: + case CK_NullToPointer: case CK_IntegralToPointer: case CK_PointerToIntegral: case CK_VectorSplat: diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 39f25f916b..d07d20395d 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -48,6 +48,13 @@ struct BinOpInfo { const Expr *E; // Entire expr, for error unsupported. May not be binop. }; +static bool MustVisitNullValue(const Expr *E) { + // If a null pointer expression's type is the C++0x nullptr_t, then + // it's not necessarily a simple constant and it must be evaluated + // for its potential side effects. + return E->getType()->isNullPtrType(); +} + class ScalarExprEmitter : public StmtVisitor { CodeGenFunction &CGF; @@ -1044,10 +1051,15 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { case CK_FunctionToPointerDecay: return EmitLValue(E).getAddress(); + case CK_NullToPointer: + if (MustVisitNullValue(E)) + (void) Visit(E); + + return llvm::ConstantPointerNull::get( + cast(ConvertType(DestTy))); + case CK_NullToMemberPointer: { - // If the subexpression's type is the C++0x nullptr_t, emit the - // subexpression, which may have side effects. - if (E->getType()->isNullPtrType()) + if (MustVisitNullValue(E)) (void) Visit(E); const MemberPointerType *MPT = CE->getType()->getAs(); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 25ad7b6a87..baeebe1e40 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -1131,7 +1131,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, // Is the source an overloaded name? (i.e. &foo) // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) - if (SrcType == Self.Context.OverloadTy ) + if (SrcType == Self.Context.OverloadTy) return TC_NotApplicable; if (const ReferenceType *DestTypeTmp = DestType->getAs()) { @@ -1270,6 +1270,8 @@ 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. + // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not + // necessarily converted to a null pointer value.] Kind = CK_IntegralToPointer; return TC_Success; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8da3846f69..6eb07b5558 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4003,7 +4003,8 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, } static CastKind getScalarCastKind(ASTContext &Context, - QualType SrcTy, QualType DestTy) { + Expr *Src, QualType DestTy) { + QualType SrcTy = Src->getType(); if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CK_NoOp; @@ -4019,8 +4020,11 @@ static CastKind getScalarCastKind(ASTContext &Context, if (SrcTy->isIntegerType()) { if (DestTy->isIntegerType()) return CK_IntegralCast; - if (DestTy->hasPointerRepresentation()) + if (DestTy->hasPointerRepresentation()) { + if (Src->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return CK_NullToPointer; return CK_IntegralToPointer; + } if (DestTy->isRealFloatingType()) return CK_IntegralToFloating; } @@ -4131,7 +4135,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, << castType << castExpr->getSourceRange(); } - Kind = getScalarCastKind(Context, castExpr->getType(), castType); + Kind = getScalarCastKind(Context, castExpr, castType); if (Kind == CK_Unknown || Kind == CK_BitCast) CheckCastAlign(castExpr, castType, TyR); @@ -4185,7 +4189,7 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, QualType DestElemTy = DestTy->getAs()->getElementType(); ImpCastExprToType(CastExpr, DestElemTy, - getScalarCastKind(Context, SrcTy, DestElemTy)); + getScalarCastKind(Context, CastExpr, DestElemTy)); Kind = CK_VectorSplat; return false; @@ -4533,7 +4537,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return LHSTy; } - // GCC compatibility: soften pointer/integer mismatch. + // GCC compatibility: soften pointer/integer mismatch. Note that + // null pointers have been filtered out by this point. if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); @@ -5104,7 +5109,7 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { if (rExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, it->getType(), CK_IntegralToPointer); + ImpCastExprToType(rExpr, it->getType(), CK_NullToPointer); InitField = *it; break; } @@ -5827,7 +5832,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, ImpCastExprToType(rex, lType, lType->isMemberPointerType() ? CK_NullToMemberPointer - : CK_IntegralToPointer); + : CK_NullToPointer); return ResultTy; } if (LHSIsNull && @@ -5836,7 +5841,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, ImpCastExprToType(lex, rType, rType->isMemberPointerType() ? CK_NullToMemberPointer - : CK_IntegralToPointer); + : CK_NullToPointer); return ResultTy; } @@ -5951,21 +5956,23 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if (lType->isIntegerType()) - ImpCastExprToType(lex, rType, CK_IntegralToPointer); + ImpCastExprToType(lex, rType, + LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); else - ImpCastExprToType(rex, lType, CK_IntegralToPointer); + ImpCastExprToType(rex, lType, + RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); return ResultTy; } // Handle block pointers. if (!isRelational && RHSIsNull && lType->isBlockPointerType() && rType->isIntegerType()) { - ImpCastExprToType(rex, lType, CK_IntegralToPointer); + ImpCastExprToType(rex, lType, CK_NullToPointer); return ResultTy; } if (!isRelational && LHSIsNull && lType->isIntegerType() && rType->isBlockPointerType()) { - ImpCastExprToType(lex, rType, CK_IntegralToPointer); + ImpCastExprToType(lex, rType, CK_NullToPointer); return ResultTy; } return InvalidOperands(Loc, lex, rex); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index e58c38cd58..b6a02518a7 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2750,14 +2750,14 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, if (T2->isMemberPointerType()) ImpCastExprToType(E1, T2, CK_NullToMemberPointer); else - ImpCastExprToType(E1, T2, CK_IntegralToPointer); + ImpCastExprToType(E1, T2, CK_NullToPointer); return T2; } if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T1->isMemberPointerType()) ImpCastExprToType(E2, T1, CK_NullToMemberPointer); else - ImpCastExprToType(E2, T1, CK_IntegralToPointer); + ImpCastExprToType(E2, T1, CK_NullToPointer); return T1; } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 5ddf94597b..be87a42a3c 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1014,9 +1014,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (ReceiverType->isPointerType()) ImpCastExprToType(Receiver, Context.getObjCIdType(), CK_BitCast); - else + else { + // TODO: specialized warning on null receivers? + bool IsNull = Receiver->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_IntegralToPointer); + IsNull ? CK_NullToPointer : CK_IntegralToPointer); + } ReceiverType = Receiver->getType(); } else if (getLangOptions().CPlusPlus &&