Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -189,6 +189,9 @@ ^^^^^^^^^^^^^^^^^^^^^ - Diagnose consteval and constexpr issues that happen at namespace scope. This partially addresses `Issue 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 `_. C++2b Feature Support ^^^^^^^^^^^^^^^^^^^^^ Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -10513,9 +10513,7 @@ template ExprResult TreeTransform::TransformUserDefinedLiteral(UserDefinedLiteral *E) { - if (FunctionDecl *FD = E->getDirectCallee()) - SemaRef.MarkFunctionReferenced(E->getBeginLoc(), FD); - return SemaRef.MaybeBindToTemporary(E); + return getDerived().TransformCallExpr(E); } template Index: clang/test/CodeGenCXX/cxx20-consteval-crash.cpp =================================================================== --- clang/test/CodeGenCXX/cxx20-consteval-crash.cpp +++ clang/test/CodeGenCXX/cxx20-consteval-crash.cpp @@ -24,3 +24,35 @@ // CHECK: ret void // CHECK: } } + +namespace Issue54578 { +inline consteval unsigned char operator""_UC(const unsigned long long n) { + return static_cast(n); +} + +inline constexpr char f1(const auto octet) { + return 4_UC; +} + +template +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 +} Index: clang/test/SemaCXX/cxx2a-consteval.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-consteval.cpp +++ clang/test/SemaCXX/cxx2a-consteval.cpp @@ -721,3 +721,27 @@ 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(n); +} + +inline constexpr char f1(const auto octet) { + return 4_UC; +} + +template +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); +} +}