]> granicus.if.org Git - clang/commitdiff
Introduce a null-to-pointer implicit cast kind.
authorJohn McCall <rjmccall@apple.com>
Sat, 13 Nov 2010 01:35:44 +0000 (01:35 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 13 Nov 2010 01:35:44 +0000 (01:35 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118966 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/AST/OperationKinds.h
lib/AST/Expr.cpp
lib/AST/ExprConstant.cpp
lib/Checker/GRExprEngine.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaExprObjC.cpp

index d7e8fd8d9083bc44ac0f3deb7e9d518cdd2185ba..be6e1bca5838284c85b964d785199e3d22b5b0de 100644 (file)
@@ -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:
index 8b01490160794fb49df1b13662fe1e2a5ce6b8f0..4e57df1af6ef0c1e7b43403dba6723ac213c5c52 100644 (file)
@@ -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,
 
index 7d05bdb26486395b9254440e09e81cb18b2e162a..2edf62ab3978eaee0e9a74890a58a6bb8372c3f5 100644 (file)
@@ -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:
index 451aa2a25329d142e61f9360bfe3fd7e4875e930..dfeb32df3d331db5bd01a527331c1e17b875a5ad 100644 (file)
@@ -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))
index 1669a353a552ae12de7d7e2bdfef4b22d76ee217..73b5bf8967efbe6038d35cb4a0aa59233b991e42 100644 (file)
@@ -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:
index 355c18f79c5ed427d7ab7905446ce4a39612811c..bb2eb3c7982c8b02128f5023e2900cf78d5180a5 100644 (file)
@@ -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:
index 39f25f916b8c2b58d1725a90229a0cacee05a447..d07d20395d549ef72677f7fbdc9da1c2e7f763f2 100644 (file)
@@ -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>();
index 25ad7b6a87c04c78659afe9b97b26662d1ff67e5..baeebe1e40901798b642b4c0d200aa7aadeaf6cd 100644 (file)
@@ -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;
   }
index 8da3846f691c6764287298735c829b6e7fe9125e..6eb07b5558530317c59498d2ed10f1c55b23821e 100644 (file)
@@ -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);
index e58c38cd5884cc7da36f930ae283d894459d871e..b6a02518a7d869bdd8ba3b34e0fb87e917968f6f 100644 (file)
@@ -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;
   }
 
index 5ddf94597bb44b03e2afbb7c9e878a2502d3dcb3..be87a42a3cf729c3cb2521cde2f08d58031befae 100644 (file)
@@ -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 &&