Skip to content

Commit

Permalink
[Clang] Always constant-evaluate operands of comparisons to nullptr
Browse files Browse the repository at this point in the history
even if we know what the result is going to be.
There may be side effects we ought not to ignore,

Fixes #64923

Reviewed By: ChuanqiXu

Differential Revision: https://reviews.llvm.org/D158601
  • Loading branch information
cor3ntin committed Aug 24, 2023
1 parent 158f4f3 commit 3f98cdc
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 0 deletions.
5 changes: 5 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ Bug Fixes to C++ Support
- Update ``FunctionDeclBitfields.NumFunctionDeclBits``. This fixes:
(`#64171 <https://github.com/llvm/llvm-project/issues/64171>`_).

- Expressions producing ``nullptr`` are correctly evaluated
by the constant interpreter when appearing as the operand
of a binary comparision.
(`#64923 <https://github.com/llvm/llvm-project/issues/64923>_``)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed an import failure of recursive friend class template.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13310,6 +13310,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
// C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t
// are compared, the result is true of the operator is <=, >= or ==, and
// false otherwise.
LValue Res;
if (!EvaluatePointer(E->getLHS(), Res, Info) ||
!EvaluatePointer(E->getRHS(), Res, Info))
return false;
return Success(CmpResult::Equal, E);
}

Expand Down
18 changes: 18 additions & 0 deletions clang/test/SemaCXX/compare-cxx2a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,21 @@ namespace PR52537 {
template<typename T> bool f6() { return 0 < y6; } // expected-note {{instantiation of}}
void g6() { f6<int>(); } // expected-note {{instantiation of}}
}


namespace GH64923 {
using nullptr_t = decltype(nullptr);
struct MyTask{};
constexpr MyTask DoAnotherThing() {
return {};
}

constexpr nullptr_t operator++(MyTask &&T); // expected-note 2{{declared here}}
void DoSomething() {
if constexpr (++DoAnotherThing() != nullptr) {} // expected-error {{constexpr if condition is not a constant expression}} \
// expected-note {{undefined function 'operator++' cannot be used in a constant expression}}

if constexpr (nullptr == ++DoAnotherThing()) {} // expected-error {{constexpr if condition is not a constant expression}} \
// expected-note {{undefined function 'operator++' cannot be used in a constant expression}}
}
}

0 comments on commit 3f98cdc

Please sign in to comment.