@@ -465,49 +465,7 @@ namespace {
465465 void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
466466 const APSInt &N);
467467 /// Add N to the address of this subobject.
468- void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N) {
469- if (Invalid || !N) return;
470- uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
471- if (isMostDerivedAnUnsizedArray()) {
472- diagnoseUnsizedArrayPointerArithmetic(Info, E);
473- // Can't verify -- trust that the user is doing the right thing (or if
474- // not, trust that the caller will catch the bad behavior).
475- // FIXME: Should we reject if this overflows, at least?
476- Entries.back() = PathEntry::ArrayIndex(
477- Entries.back().getAsArrayIndex() + TruncatedN);
478- return;
479- }
480-
481- // [expr.add]p4: For the purposes of these operators, a pointer to a
482- // nonarray object behaves the same as a pointer to the first element of
483- // an array of length one with the type of the object as its element type.
484- bool IsArray = MostDerivedPathLength == Entries.size() &&
485- MostDerivedIsArrayElement;
486- uint64_t ArrayIndex = IsArray ? Entries.back().getAsArrayIndex()
487- : (uint64_t)IsOnePastTheEnd;
488- uint64_t ArraySize =
489- IsArray ? getMostDerivedArraySize() : (uint64_t)1;
490-
491- if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) {
492- // Calculate the actual index in a wide enough type, so we can include
493- // it in the note.
494- N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65));
495- (llvm::APInt&)N += ArrayIndex;
496- assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index");
497- diagnosePointerArithmetic(Info, E, N);
498- setInvalid();
499- return;
500- }
501-
502- ArrayIndex += TruncatedN;
503- assert(ArrayIndex <= ArraySize &&
504- "bounds check succeeded for out-of-bounds index");
505-
506- if (IsArray)
507- Entries.back() = PathEntry::ArrayIndex(ArrayIndex);
508- else
509- IsOnePastTheEnd = (ArrayIndex != 0);
510- }
468+ void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N, LValue &LV);
511469 };
512470
513471 /// A scope at the end of which an object can need to be destroyed.
@@ -1799,7 +1757,7 @@ namespace {
17991757 Offset = CharUnits::fromQuantity(Offset64 + ElemSize64 * Index64);
18001758
18011759 if (checkNullPointer(Info, E, CSK_ArrayIndex))
1802- Designator.adjustIndex(Info, E, Index);
1760+ Designator.adjustIndex(Info, E, Index, *this );
18031761 clearIsNullPointer();
18041762 }
18051763 void adjustOffset(CharUnits N) {
@@ -1907,6 +1865,54 @@ namespace {
19071865 }
19081866}
19091867
1868+ void SubobjectDesignator::adjustIndex(EvalInfo &Info, const Expr *E, APSInt N,
1869+ LValue &LV) {
1870+ if (Invalid || !N)
1871+ return;
1872+ uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
1873+ if (isMostDerivedAnUnsizedArray()) {
1874+ diagnoseUnsizedArrayPointerArithmetic(Info, E);
1875+ // Can't verify -- trust that the user is doing the right thing (or if
1876+ // not, trust that the caller will catch the bad behavior).
1877+ // FIXME: Should we reject if this overflows, at least?
1878+ Entries.back() =
1879+ PathEntry::ArrayIndex(Entries.back().getAsArrayIndex() + TruncatedN);
1880+ return;
1881+ }
1882+
1883+ // [expr.add]p4: For the purposes of these operators, a pointer to a
1884+ // nonarray object behaves the same as a pointer to the first element of
1885+ // an array of length one with the type of the object as its element type.
1886+ bool IsArray =
1887+ MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement;
1888+ uint64_t ArrayIndex =
1889+ IsArray ? Entries.back().getAsArrayIndex() : (uint64_t)IsOnePastTheEnd;
1890+ uint64_t ArraySize = IsArray ? getMostDerivedArraySize() : (uint64_t)1;
1891+
1892+ if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) {
1893+ if (!Info.checkingPotentialConstantExpression() ||
1894+ !LV.AllowConstexprUnknown) {
1895+ // Calculate the actual index in a wide enough type, so we can include
1896+ // it in the note.
1897+ N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65));
1898+ (llvm::APInt &)N += ArrayIndex;
1899+ assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index");
1900+ diagnosePointerArithmetic(Info, E, N);
1901+ }
1902+ setInvalid();
1903+ return;
1904+ }
1905+
1906+ ArrayIndex += TruncatedN;
1907+ assert(ArrayIndex <= ArraySize &&
1908+ "bounds check succeeded for out-of-bounds index");
1909+
1910+ if (IsArray)
1911+ Entries.back() = PathEntry::ArrayIndex(ArrayIndex);
1912+ else
1913+ IsOnePastTheEnd = (ArrayIndex != 0);
1914+ }
1915+
19101916static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E);
19111917static bool EvaluateInPlace(APValue &Result, EvalInfo &Info,
19121918 const LValue &This, const Expr *E,
@@ -5126,12 +5132,18 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E,
51265132 if (const PointerType *PT = TargetQT->getAs<PointerType>())
51275133 TargetQT = PT->getPointeeType();
51285134
5129- // Check this cast lands within the final derived-to-base subobject path.
5130- if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) {
5131- Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
5132- << D.MostDerivedType << TargetQT;
5135+ auto InvalidCast = [&]() {
5136+ if (!Info.checkingPotentialConstantExpression() ||
5137+ !Result.AllowConstexprUnknown) {
5138+ Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
5139+ << D.MostDerivedType << TargetQT;
5140+ }
51335141 return false;
5134- }
5142+ };
5143+
5144+ // Check this cast lands within the final derived-to-base subobject path.
5145+ if (D.MostDerivedPathLength + E->path_size() > D.Entries.size())
5146+ return InvalidCast();
51355147
51365148 // Check the type of the final cast. We don't need to check the path,
51375149 // since a cast can only be formed if the path is unique.
@@ -5142,11 +5154,8 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E,
51425154 FinalType = D.MostDerivedType->getAsCXXRecordDecl();
51435155 else
51445156 FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]);
5145- if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) {
5146- Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
5147- << D.MostDerivedType << TargetQT;
5148- return false;
5149- }
5157+ if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl())
5158+ return InvalidCast();
51505159
51515160 // Truncate the lvalue to the appropriate derived class.
51525161 return CastToDerivedClass(Info, E, Result, TargetType, NewEntriesSize);
@@ -6104,12 +6113,15 @@ static bool checkDynamicType(EvalInfo &Info, const Expr *E, const LValue &This,
61046113 } else if (Polymorphic) {
61056114 // Conservatively refuse to perform a polymorphic operation if we would
61066115 // not be able to read a notional 'vptr' value.
6107- APValue Val;
6108- This.moveInto(Val);
6109- QualType StarThisType =
6110- Info.Ctx.getLValueReferenceType(This.Designator.getType(Info.Ctx));
6111- Info.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
6112- << AK << Val.getAsString(Info.Ctx, StarThisType);
6116+ if (!Info.checkingPotentialConstantExpression() ||
6117+ !This.AllowConstexprUnknown) {
6118+ APValue Val;
6119+ This.moveInto(Val);
6120+ QualType StarThisType =
6121+ Info.Ctx.getLValueReferenceType(This.Designator.getType(Info.Ctx));
6122+ Info.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
6123+ << AK << Val.getAsString(Info.Ctx, StarThisType);
6124+ }
61136125 return false;
61146126 }
61156127 return true;
@@ -14554,6 +14566,11 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
1455414566 // Reject differing bases from the normal codepath; we special-case
1455514567 // comparisons to null.
1455614568 if (!HasSameBase(LHSValue, RHSValue)) {
14569+ // Bail out early if we're checking potential constant expression.
14570+ // Otherwise, prefer to diagnose other issues.
14571+ if (Info.checkingPotentialConstantExpression() &&
14572+ (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
14573+ return false;
1455714574 auto DiagComparison = [&] (unsigned DiagID, bool Reversed = false) {
1455814575 std::string LHS = LHSValue.toString(Info.Ctx, E->getLHS()->getType());
1455914576 std::string RHS = RHSValue.toString(Info.Ctx, E->getRHS()->getType());
@@ -14874,6 +14891,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1487414891 // Reject differing bases from the normal codepath; we special-case
1487514892 // comparisons to null.
1487614893 if (!HasSameBase(LHSValue, RHSValue)) {
14894+ if (Info.checkingPotentialConstantExpression() &&
14895+ (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
14896+ return false;
14897+
1487714898 const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr *>();
1487814899 const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr *>();
1487914900
0 commit comments