diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -455,6 +455,8 @@ - Fix crash when diagnosing default comparison method. (`#62791 `_) and (`#62102 `_). +- Fix reject-valid when consteval operator appears inside of a template. + (`#62886 `_). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11937,10 +11937,6 @@ llvm_unreachable("not an overloaded operator?"); } - ExprResult Callee = getDerived().TransformExpr(E->getCallee()); - if (Callee.isInvalid()) - return ExprError(); - ExprResult First; if (E->getOperator() == OO_Amp) First = getDerived().TransformAddressOfOperand(E->getArg(0)); @@ -11957,23 +11953,15 @@ return ExprError(); } - if (!getDerived().AlwaysRebuild() && - Callee.get() == E->getCallee() && - First.get() == E->getArg(0) && - (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) - return SemaRef.MaybeBindToTemporary(E); - Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); FPOptionsOverride NewOverrides(E->getFPFeatures()); getSema().CurFPFeatures = NewOverrides.applyOverrides(getSema().getLangOpts()); getSema().FpPragmaStack.CurrentValue = NewOverrides; - return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), - E->getOperatorLoc(), - Callee.get(), - First.get(), - Second.get()); + return getDerived().RebuildCXXOperatorCallExpr( + E->getOperator(), E->getOperatorLoc(), E->getCallee(), First.get(), + Second.get()); } template diff --git a/clang/test/SemaCXX/consteval-operators.cpp b/clang/test/SemaCXX/consteval-operators.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/consteval-operators.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++2a -emit-llvm-only -Wno-unused-value %s -verify + +// expected-no-diagnostics + +struct A { + consteval A operator+() { return {}; } +}; +consteval A operator~(A) { return {}; } +consteval A operator+(A, A) { return {}; } + +template void f() { + A a; + A b = ~a; + A c = a + a; + A d = +a; +} +template void f(); + +template void foo() { + T a; + T b = ~a; + T c = a + a; + T d = +a; +} + +template void foo(); + +template struct B { DataT D; }; + +template +consteval B operator+(B lhs, B rhs) { + return B{lhs.D + rhs.D}; +} + +template consteval T template_add(T a, T b) { return a + b; } + +consteval B non_template_add(B a, B b) { return a + b; } + +void bar() { + constexpr B a{}; + constexpr B b{}; + auto constexpr c = a + b; +} + +static_assert((template_add(B{7}, B{3})).D == 10); +static_assert((non_template_add(B{7}, B{3})).D == 10);