aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-25 04:25:58 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-25 04:25:58 +0000
commitce94049b69f75b44c18584fe79cd238978b6b0d5 (patch)
treee7075c52e30004d24fb813d4847b32e6a1d9f76d /lib/Sema
parentd52025366666647e3f876e3615200dcf8c80279c (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.h1
-rw-r--r--lib/Sema/SemaChecking.cpp5
-rw-r--r--lib/Sema/SemaExpr.cpp33
-rw-r--r--lib/Sema/SemaExprCXX.cpp10
-rw-r--r--lib/Sema/SemaOverload.cpp18
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;