diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-25 04:25:58 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-25 04:25:58 +0000 |
commit | ce94049b69f75b44c18584fe79cd238978b6b0d5 (patch) | |
tree | e7075c52e30004d24fb813d4847b32e6a1d9f76d /lib/Sema | |
parent | d52025366666647e3f876e3615200dcf8c80279c (diff) |
Fix checking for a null pointer constant when the expression itself is
value-dependent. Audit (and fixed) all calls to
Expr::isNullPointerConstant() to provide the correct behavior with
value-dependent expressions. Fixes PR5041 and a crash in libstdc++
<locale>.
In the same vein, properly compute value- and type-dependence for
ChooseExpr. Fixes PR4996.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82748 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 18 |
5 files changed, 46 insertions, 21 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0bb72568b1..8377d50939 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -782,6 +782,7 @@ public: bool CheckPointerConversion(Expr *From, QualType ToType, CastExpr::CastKind &Kind); bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, QualType &ConvertedType); bool CheckMemberPointerConversion(Expr *From, QualType ToType, CastExpr::CastKind &Kind); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 18a997998a..92bf83f083 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -93,7 +93,7 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { unsigned format_idx = Format->getFormatIdx() - 1; if (format_idx < TheCall->getNumArgs()) { Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts(); - if (!Format->isNullPointerConstant(Context)) + if (!Format->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) return true; } } @@ -911,7 +911,8 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull, for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end(); i != e; ++i) { const Expr *ArgExpr = TheCall->getArg(*i); - if (ArgExpr->isNullPointerConstant(Context)) + if (ArgExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull)) Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg) << ArgExpr->getSourceRange(); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5bc8818dba..2f653b5320 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -173,7 +173,8 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, } Expr *sentinelExpr = Args[sentinel]; if (sentinelExpr && (!sentinelExpr->getType()->isPointerType() || - !sentinelExpr->isNullPointerConstant(Context))) { + !sentinelExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull))) { Diag(Loc, diag::warn_missing_sentinel) << isMethod; Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; } @@ -3395,12 +3396,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has // the type of the other operand." if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) && - RHS->isNullPointerConstant(Context)) { + RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(RHS, LHSTy); // promote the null to a pointer. return LHSTy; } if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) && - LHS->isNullPointerConstant(Context)) { + LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer. return RHSTy; } @@ -3982,7 +3983,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { break; } - if (rExpr->isNullPointerConstant(Context)) { + if (rExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(rExpr, it->getType()); InitField = *it; break; @@ -4025,7 +4027,8 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { if ((lhsType->isPointerType() || lhsType->isObjCObjectPointerType() || lhsType->isBlockPointerType()) - && rExpr->isNullPointerConstant(Context)) { + && rExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(rExpr, lhsType); return Compatible; } @@ -4454,12 +4457,14 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, Expr *literalString = 0; Expr *literalStringStripped = 0; if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) && - !RHSStripped->isNullPointerConstant(Context)) { + !RHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { literalString = lex; literalStringStripped = LHSStripped; } else if ((isa<StringLiteral>(RHSStripped) || isa<ObjCEncodeExpr>(RHSStripped)) && - !LHSStripped->isNullPointerConstant(Context)) { + !LHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { literalString = rex; literalStringStripped = RHSStripped; } @@ -4504,8 +4509,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return ResultTy; } - bool LHSIsNull = lex->isNullPointerConstant(Context); - bool RHSIsNull = rex->isNullPointerConstant(Context); + bool LHSIsNull = lex->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + bool RHSIsNull = rex->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); // All of the following pointer related warnings are GCC extensions, except // when handling null pointer constants. One day, we can consider making them @@ -5721,8 +5728,10 @@ Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)"); QualType resType; + bool ValueDependent = false; if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) { resType = Context.DependentTy; + ValueDependent = true; } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); @@ -5734,11 +5743,15 @@ Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, // If the condition is > zero, then the AST type is the same as the LSHExpr. resType = condEval.getZExtValue() ? LHSExpr->getType() : RHSExpr->getType(); + ValueDependent = condEval.getZExtValue() ? LHSExpr->isValueDependent() + : RHSExpr->isValueDependent(); } cond.release(); expr1.release(); expr2.release(); return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, - resType, RPLoc)); + resType, RPLoc, + resType->isDependentType(), + ValueDependent)); } //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index e93929e94b..a243b2cec6 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1648,11 +1648,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // frankly, is stupid.) const MemberPointerType *LMemPtr = LTy->getAs<MemberPointerType>(); const MemberPointerType *RMemPtr = RTy->getAs<MemberPointerType>(); - if (LMemPtr && RHS->isNullPointerConstant(Context)) { + if (LMemPtr && + RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(RHS, LTy); return LTy; } - if (RMemPtr && LHS->isNullPointerConstant(Context)) { + if (RMemPtr && + LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(LHS, RTy); return RTy; } @@ -1743,11 +1745,11 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { // pointer operands to bring them to their composite pointer type. If // one operand is a null pointer constant, the composite pointer type is // the type of the other operand. - if (E1->isNullPointerConstant(Context)) { + if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(E1, T2); return T2; } - if (E2->isNullPointerConstant(Context)) { + if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(E2, T1); return T1; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6200beb863..bec61ea63a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -633,7 +633,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // Pointer conversions (C++ 4.10). SCS.Second = ICK_Pointer_Conversion; SCS.IncompatibleObjC = IncompatibleObjC; - } else if (IsMemberPointerConversion(From, FromType, ToType, FromType)) { + } else if (IsMemberPointerConversion(From, FromType, ToType, + InOverloadResolution, FromType)) { // Pointer to member conversions (4.11). SCS.Second = ICK_Pointer_Member; } else if (ToType->isBooleanType() && @@ -883,7 +884,9 @@ static bool isNullPointerConstantForConversion(Expr *Expr, Expr->getType()->isIntegralType()) return !InOverloadResolution; - return Expr->isNullPointerConstant(Context); + return Expr->isNullPointerConstant(Context, + InOverloadResolution? Expr::NPC_ValueDependentIsNotNull + : Expr::NPC_ValueDependentIsNull); } /// IsPointerConversion - Determines whether the conversion of the @@ -1188,13 +1191,17 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, /// If so, returns true and places the converted type (that might differ from /// ToType in its cv-qualifiers at some level) into ConvertedType. bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, - QualType ToType, QualType &ConvertedType) { + QualType ToType, + bool InOverloadResolution, + QualType &ConvertedType) { const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>(); if (!ToTypePtr) return false; // A null pointer constant can be converted to a member pointer (C++ 4.11p1) - if (From->isNullPointerConstant(Context)) { + if (From->isNullPointerConstant(Context, + InOverloadResolution? Expr::NPC_ValueDependentIsNotNull + : Expr::NPC_ValueDependentIsNull)) { ConvertedType = ToType; return true; } @@ -1231,7 +1238,8 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>(); if (!FromPtrType) { // This must be a null pointer to member pointer conversion - assert(From->isNullPointerConstant(Context) && + assert(From->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull) && "Expr must be null pointer constant!"); Kind = CastExpr::CK_NullToMemberPointer; return false; |