diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Checker/GRExprEngine.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 31 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 8 | 
9 files changed, 55 insertions, 20 deletions
| diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 7d05bdb2648..2edf62ab397 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/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/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 451aa2a2532..dfeb32df3d3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp index 1669a353a55..73b5bf8967e 100644 --- a/clang/lib/Checker/GRExprEngine.cpp +++ b/clang/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/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 355c18f79c5..bb2eb3c7982 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/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/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 39f25f916b8..d07d20395d5 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/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/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 25ad7b6a87c..baeebe1e409 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8da3846f691..6eb07b55585 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e58c38cd588..b6a02518a7d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 5ddf94597bb..be87a42a3cf 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/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 && | 

