@@ -456,49 +456,7 @@ namespace {
456456 void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
457457 const APSInt &N);
458458 /// Add N to the address of this subobject.
459- void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N) {
460- if (Invalid || !N) return;
461- uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
462- if (isMostDerivedAnUnsizedArray()) {
463- diagnoseUnsizedArrayPointerArithmetic(Info, E);
464- // Can't verify -- trust that the user is doing the right thing (or if
465- // not, trust that the caller will catch the bad behavior).
466- // FIXME: Should we reject if this overflows, at least?
467- Entries.back() = PathEntry::ArrayIndex(
468- Entries.back().getAsArrayIndex() + TruncatedN);
469- return;
470- }
471-
472- // [expr.add]p4: For the purposes of these operators, a pointer to a
473- // nonarray object behaves the same as a pointer to the first element of
474- // an array of length one with the type of the object as its element type.
475- bool IsArray = MostDerivedPathLength == Entries.size() &&
476- MostDerivedIsArrayElement;
477- uint64_t ArrayIndex = IsArray ? Entries.back().getAsArrayIndex()
478- : (uint64_t)IsOnePastTheEnd;
479- uint64_t ArraySize =
480- IsArray ? getMostDerivedArraySize() : (uint64_t)1;
481-
482- if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) {
483- // Calculate the actual index in a wide enough type, so we can include
484- // it in the note.
485- N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65));
486- (llvm::APInt&)N += ArrayIndex;
487- assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index");
488- diagnosePointerArithmetic(Info, E, N);
489- setInvalid();
490- return;
491- }
492-
493- ArrayIndex += TruncatedN;
494- assert(ArrayIndex <= ArraySize &&
495- "bounds check succeeded for out-of-bounds index");
496-
497- if (IsArray)
498- Entries.back() = PathEntry::ArrayIndex(ArrayIndex);
499- else
500- IsOnePastTheEnd = (ArrayIndex != 0);
501- }
459+ void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N, const LValue &LV);
502460 };
503461
504462 /// A scope at the end of which an object can need to be destroyed.
@@ -1795,7 +1753,7 @@ namespace {
17951753 Offset = CharUnits::fromQuantity(Offset64 + ElemSize64 * Index64);
17961754
17971755 if (checkNullPointer(Info, E, CSK_ArrayIndex))
1798- Designator.adjustIndex(Info, E, Index);
1756+ Designator.adjustIndex(Info, E, Index, *this );
17991757 clearIsNullPointer();
18001758 }
18011759 void adjustOffset(CharUnits N) {
@@ -1903,6 +1861,54 @@ namespace {
19031861 }
19041862}
19051863
1864+ void SubobjectDesignator::adjustIndex(EvalInfo &Info, const Expr *E, APSInt N,
1865+ const LValue &LV) {
1866+ if (Invalid || !N)
1867+ return;
1868+ uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
1869+ if (isMostDerivedAnUnsizedArray()) {
1870+ diagnoseUnsizedArrayPointerArithmetic(Info, E);
1871+ // Can't verify -- trust that the user is doing the right thing (or if
1872+ // not, trust that the caller will catch the bad behavior).
1873+ // FIXME: Should we reject if this overflows, at least?
1874+ Entries.back() =
1875+ PathEntry::ArrayIndex(Entries.back().getAsArrayIndex() + TruncatedN);
1876+ return;
1877+ }
1878+
1879+ // [expr.add]p4: For the purposes of these operators, a pointer to a
1880+ // nonarray object behaves the same as a pointer to the first element of
1881+ // an array of length one with the type of the object as its element type.
1882+ bool IsArray =
1883+ MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement;
1884+ uint64_t ArrayIndex =
1885+ IsArray ? Entries.back().getAsArrayIndex() : (uint64_t)IsOnePastTheEnd;
1886+ uint64_t ArraySize = IsArray ? getMostDerivedArraySize() : (uint64_t)1;
1887+
1888+ if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) {
1889+ if (!Info.checkingPotentialConstantExpression() ||
1890+ !LV.AllowConstexprUnknown) {
1891+ // Calculate the actual index in a wide enough type, so we can include
1892+ // it in the note.
1893+ N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65));
1894+ (llvm::APInt &)N += ArrayIndex;
1895+ assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index");
1896+ diagnosePointerArithmetic(Info, E, N);
1897+ }
1898+ setInvalid();
1899+ return;
1900+ }
1901+
1902+ ArrayIndex += TruncatedN;
1903+ assert(ArrayIndex <= ArraySize &&
1904+ "bounds check succeeded for out-of-bounds index");
1905+
1906+ if (IsArray)
1907+ Entries.back() = PathEntry::ArrayIndex(ArrayIndex);
1908+ else
1909+ IsOnePastTheEnd = (ArrayIndex != 0);
1910+ }
1911+
19061912static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E);
19071913static bool EvaluateInPlace(APValue &Result, EvalInfo &Info,
19081914 const LValue &This, const Expr *E,
@@ -5144,12 +5150,18 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E,
51445150 if (const PointerType *PT = TargetQT->getAs<PointerType>())
51455151 TargetQT = PT->getPointeeType();
51465152
5147- // Check this cast lands within the final derived-to-base subobject path.
5148- if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) {
5149- Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
5150- << D.MostDerivedType << TargetQT;
5153+ auto InvalidCast = [&]() {
5154+ if (!Info.checkingPotentialConstantExpression() ||
5155+ !Result.AllowConstexprUnknown) {
5156+ Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
5157+ << D.MostDerivedType << TargetQT;
5158+ }
51515159 return false;
5152- }
5160+ };
5161+
5162+ // Check this cast lands within the final derived-to-base subobject path.
5163+ if (D.MostDerivedPathLength + E->path_size() > D.Entries.size())
5164+ return InvalidCast();
51535165
51545166 // Check the type of the final cast. We don't need to check the path,
51555167 // since a cast can only be formed if the path is unique.
@@ -5160,11 +5172,8 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E,
51605172 FinalType = D.MostDerivedType->getAsCXXRecordDecl();
51615173 else
51625174 FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]);
5163- if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) {
5164- Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
5165- << D.MostDerivedType << TargetQT;
5166- return false;
5167- }
5175+ if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl())
5176+ return InvalidCast();
51685177
51695178 // Truncate the lvalue to the appropriate derived class.
51705179 return CastToDerivedClass(Info, E, Result, TargetType, NewEntriesSize);
@@ -6165,12 +6174,15 @@ static bool checkDynamicType(EvalInfo &Info, const Expr *E, const LValue &This,
61656174 } else if (Polymorphic) {
61666175 // Conservatively refuse to perform a polymorphic operation if we would
61676176 // not be able to read a notional 'vptr' value.
6168- APValue Val;
6169- This.moveInto(Val);
6170- QualType StarThisType =
6171- Info.Ctx.getLValueReferenceType(This.Designator.getType(Info.Ctx));
6172- Info.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
6173- << AK << Val.getAsString(Info.Ctx, StarThisType);
6177+ if (!Info.checkingPotentialConstantExpression() ||
6178+ !This.AllowConstexprUnknown) {
6179+ APValue Val;
6180+ This.moveInto(Val);
6181+ QualType StarThisType =
6182+ Info.Ctx.getLValueReferenceType(This.Designator.getType(Info.Ctx));
6183+ Info.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
6184+ << AK << Val.getAsString(Info.Ctx, StarThisType);
6185+ }
61746186 return false;
61756187 }
61766188 return true;
@@ -15075,6 +15087,11 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
1507515087 // Reject differing bases from the normal codepath; we special-case
1507615088 // comparisons to null.
1507715089 if (!HasSameBase(LHSValue, RHSValue)) {
15090+ // Bail out early if we're checking potential constant expression.
15091+ // Otherwise, prefer to diagnose other issues.
15092+ if (Info.checkingPotentialConstantExpression() &&
15093+ (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
15094+ return false;
1507815095 auto DiagComparison = [&] (unsigned DiagID, bool Reversed = false) {
1507915096 std::string LHS = LHSValue.toString(Info.Ctx, E->getLHS()->getType());
1508015097 std::string RHS = RHSValue.toString(Info.Ctx, E->getRHS()->getType());
@@ -15395,6 +15412,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1539515412 // Reject differing bases from the normal codepath; we special-case
1539615413 // comparisons to null.
1539715414 if (!HasSameBase(LHSValue, RHSValue)) {
15415+ if (Info.checkingPotentialConstantExpression() &&
15416+ (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
15417+ return false;
15418+
1539815419 const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr *>();
1539915420 const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr *>();
1540015421
0 commit comments