Author: Richard Smith Date: 2021-01-11T13:19:00-08:00 New Revision: 9b222b108a2e37eb45d3156ec8554d148d658a8a
URL: https://github.com/llvm/llvm-project/commit/9b222b108a2e37eb45d3156ec8554d148d658a8a DIFF: https://github.com/llvm/llvm-project/commit/9b222b108a2e37eb45d3156ec8554d148d658a8a.diff LOG: [c++20] Don't consider string literal operator templates for numeric literals. A literal interpretation of the standard wording allows this, but it was never intended that string literal operator templates would be used for anything other than user-defined string literals. Added: Modified: clang/lib/Sema/SemaLookup.cpp clang/test/SemaCXX/cxx2a-user-defined-literals.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 16dd8f5105961..29038ab9fe1ca 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3384,6 +3384,13 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, TemplateParameterList *Params = FD->getTemplateParameters(); if (Params->size() == 1) { IsTemplate = true; + if (!Params->getParam(0)->isTemplateParameterPack() && !StringLit) { + // Implied but not stated: user-defined integer and floating literals + // only ever use numeric literal operator templates, not templates + // taking a parameter of class type. + F.erase(); + continue; + } // A string literal template is only considered if the string literal // is a well-formed template argument for the template parameter. diff --git a/clang/test/SemaCXX/cxx2a-user-defined-literals.cpp b/clang/test/SemaCXX/cxx2a-user-defined-literals.cpp index d730eba741a88..12f672ff640a9 100644 --- a/clang/test/SemaCXX/cxx2a-user-defined-literals.cpp +++ b/clang/test/SemaCXX/cxx2a-user-defined-literals.cpp @@ -24,4 +24,33 @@ chrono::day bin_d = 0b011d; // expected-note@9{{candidate constructor (the implicit move constructor)}} chrono::day hex_d = 0x44d; chrono::year y = 10y; + +namespace ignore_class_udl_for_numeric_literals { + struct A { constexpr A(const char*) {} }; + struct B { constexpr B(char); }; + struct C { constexpr C(int); }; + template<A> void operator""_a(); + template<B> void operator""_b(); + template<C> void operator""_c(); + void test_class_udl_1() { + 1_a; // expected-error {{no matching}} + 1_b; // expected-error {{no matching}} + 1_c; // expected-error {{no matching}} + "1"_a; + "1"_b; // expected-error {{no matching}} + "1"_c; // expected-error {{no matching}} + } + template<char...> void operator""_a(); + template<char...> void operator""_b(); + template<char...> void operator""_c(); + void test_class_udl_2() { + 1_a; + // FIXME: The standard appears to say these two are ambiguous! + 1_b; + 1_c; + "1"_a; + "1"_b; // expected-error {{no matching}} + "1"_c; // expected-error {{no matching}} + } +} #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits