^^^^^^^^^^^^^^^^^^^^^
- Diagnose consteval and constexpr issues that happen at namespace scope. This
partially addresses `Issue 51593 <https://github.com/llvm/llvm-project/issues/51593>`_.
+- No longer attempt to evaluate a consteval UDL function call at runtime when
+ it is called through a template instantiation. This fixes
+ `Issue 54578 <https://github.com/llvm/llvm-project/issues/54578>`_.
C++2b Feature Support
^^^^^^^^^^^^^^^^^^^^^
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) {
- if (FunctionDecl *FD = E->getDirectCallee())
- SemaRef.MarkFunctionReferenced(E->getBeginLoc(), FD);
- return SemaRef.MaybeBindToTemporary(E);
+ return getDerived().TransformCallExpr(E);
}
template<typename Derived>
// CHECK: ret void
// CHECK: }
}
+
+namespace Issue54578 {
+inline consteval unsigned char operator""_UC(const unsigned long long n) {
+ return static_cast<unsigned char>(n);
+}
+
+inline constexpr char f1(const auto octet) {
+ return 4_UC;
+}
+
+template <typename Ty>
+inline constexpr char f2(const Ty octet) {
+ return 4_UC;
+}
+
+int foo() {
+ return f1('a') + f2('a');
+}
+
+// Because the consteval functions are inline (implicitly as well as
+// explicitly), we need to defer the CHECK lines until this point to get the
+// order correct. We want to ensure there is no definition of the consteval
+// UDL function, and that the constexpr f1 and f2 functions both return a
+// constant value.
+
+// CHECK-NOT: define{{.*}} zeroext i8 @_ZN10Issue54578li3_UCEy
+// CHECK: define{{.*}} i32 @_ZN10Issue545783fooEv(
+// CHECK: define{{.*}} signext i8 @_ZN10Issue545782f1IcEEcT_(
+// CHECK: ret i8 4
+// CHECK: define{{.*}} signext i8 @_ZN10Issue545782f2IcEEcT_(
+// CHECK: ret i8 4
+}
expected-note {{subobject of type 'int' is not initialized}}
} // namespace NamespaceScopeConsteval
+
+namespace Issue54578 {
+// We expect the user-defined literal to be resovled entirely at compile time
+// despite being instantiated through a template.
+inline consteval unsigned char operator""_UC(const unsigned long long n) {
+ return static_cast<unsigned char>(n);
+}
+
+inline constexpr char f1(const auto octet) {
+ return 4_UC;
+}
+
+template <typename Ty>
+inline constexpr char f2(const Ty octet) {
+ return 4_UC;
+}
+
+void test() {
+ static_assert(f1('a') == 4);
+ static_assert(f2('a') == 4);
+ constexpr int c = f1('a') + f2('a');
+ static_assert(c == 8);
+}
+}