aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-11-13 01:35:44 +0000
committerJohn McCall <rjmccall@apple.com>2010-11-13 01:35:44 +0000
commit404cd1669c3ba138a9ae0a619bd689cce5aae271 (patch)
treea053c793cd8d0204c8b52a673e79aa7d387ba52d
parent73d15c452e675b684b7eee4f2096e386e59397aa (diff)
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
-rw-r--r--include/clang/AST/Expr.h1
-rw-r--r--include/clang/AST/OperationKinds.h3
-rw-r--r--lib/AST/Expr.cpp2
-rw-r--r--lib/AST/ExprConstant.cpp6
-rw-r--r--lib/Checker/GRExprEngine.cpp1
-rw-r--r--lib/CodeGen/CGExpr.cpp1
-rw-r--r--lib/CodeGen/CGExprScalar.cpp18
-rw-r--r--lib/Sema/SemaCXXCast.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp31
-rw-r--r--lib/Sema/SemaExprCXX.cpp4
-rw-r--r--lib/Sema/SemaExprObjC.cpp8
11 files changed, 59 insertions, 20 deletions
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<ScalarExprEmitter, Value*> {
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<llvm::PointerType>(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<MemberPointerType>();
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<ReferenceType>()) {
@@ -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<ExtVectorType>()->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 &&