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
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0bb7256..8377d50 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -782,6 +782,7 @@
   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 18a9979..92bf83f 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -93,7 +93,7 @@
     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 @@
   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 5bc8818..2f653b5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -173,7 +173,8 @@
   }
   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 @@
   // 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 @@
           break;
         }
 
-      if (rExpr->isNullPointerConstant(Context)) {
+      if (rExpr->isNullPointerConstant(Context, 
+                                       Expr::NPC_ValueDependentIsNull)) {
         ImpCastExprToType(rExpr, it->getType());
         InitField = *it;
         break;
@@ -4025,7 +4027,8 @@
   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 @@
     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 @@
       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 @@
   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 @@
 
     // 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 e93929e..a243b2c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1648,11 +1648,13 @@
   // 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 @@
   //   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 6200beb..bec61ea 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -633,7 +633,8 @@
     // 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 @@
       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 @@
 /// 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 @@
   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;