Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix template instantiation of UDLs #45

Merged
merged 1 commit into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ C++20 Feature Support
macros and is not affected by these changes. The ``<stdatomic.h>`` diagnostic
can be disabled by defining the ``_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS``
macro prior to including the header.
- 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
^^^^^^^^^^^^^^^^^^^^^
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -10460,9 +10460,7 @@ TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
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>
Expand Down
32 changes: 32 additions & 0 deletions clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,35 @@ void f() { g(); }
// 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
}
32 changes: 28 additions & 4 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ consteval int f1(int i) {
return i;
}

consteval constexpr int f2(int i) {
consteval constexpr int f2(int i) {
//expected-error@-1 {{cannot combine}}
return i;
}
Expand Down Expand Up @@ -195,7 +195,7 @@ auto ptr = ret1(0);
struct A {
consteval int f(int) {
// expected-note@-1+ {{declared here}}
return 0;
return 0;
}
};

Expand Down Expand Up @@ -239,7 +239,7 @@ constexpr int f_c(int i) {
int t = f(i);
// expected-error@-1 {{is not a constant expression}}
// expected-note@-2 {{function parameter}}
return f(0);
return f(0);
}

consteval int f_eval(int i) {
Expand All @@ -255,7 +255,7 @@ auto l1 = [](int i) constexpr {
int t = f(i);
// expected-error@-1 {{is not a constant expression}}
// expected-note@-2 {{function parameter}}
return f(0);
return f(0);
};

}
Expand Down Expand Up @@ -663,3 +663,27 @@ struct A {
}
};
} // PR48235

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);
}
}