From 0722b8ab8168d9e1aa3413a62c65878f407225ae Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Fri, 30 Aug 2024 16:29:18 +0800 Subject: [PATCH] [Clang][NFC] Consolidate tests for default argument substitution (#105617) Follow-up on 8ac140f39. The test `SemaTemplate/default-parm-init.cpp` was introduced since the fix #80288 and mainly did the following things: - Ensure the default arguments are properly substituted inside either the primary template & their explicit / out-of-line specializations. - Ensure the strategy doesn't mess up the substitution of a lambda expression as a default argument. The 1st is for the bug of #68490, yet it does some redundant work: each of the member functions is duplicated twice for the `sizeof` and `alignof` operators, respectively, and the principle under the hood are essentially the same. So this patch removes the duplication and reduces the 8 functions to 4 functions that reveal the same thing. The 2nd is presumably testing that the fix in #80288 doesn't impact a complicated substitution. However, that seems unnecessary & unrelated to the original issue. And more importantly, we don't have any problems with that ever. Hence, I'll remove that test from this patch. The test for default arguments is merged into `SemaTemplate/default-arguments.cpp` with a new namespace, and hopefully this could reduce the entropy of our testing cases. --- clang/test/SemaTemplate/default-arguments.cpp | 52 +++++ clang/test/SemaTemplate/default-parm-init.cpp | 190 ------------------ 2 files changed, 52 insertions(+), 190 deletions(-) delete mode 100644 clang/test/SemaTemplate/default-parm-init.cpp diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp index d5d9687cc90f..3b1fbda414c1 100644 --- a/clang/test/SemaTemplate/default-arguments.cpp +++ b/clang/test/SemaTemplate/default-arguments.cpp @@ -229,3 +229,55 @@ namespace unevaluated { template int f(int = a); // expected-warning 0-1{{extension}} int k = sizeof(f()); } + +#if __cplusplus >= 201103L +namespace GH68490 { + +template struct S { + template + constexpr int SizeOfU(int param = sizeof(U)) const; + + template + constexpr int SizeOfT(int param = sizeof(T)) const; +}; + +template struct S { + template + constexpr int SizeOfU(int param = sizeof(U)) const; + + template + constexpr int SizeOfT(int param = sizeof(T *)) const; +}; + +template +template +constexpr int S::SizeOfU(int param) const { + return param; +} + +template +template +constexpr int S::SizeOfT(int param) const { + return param; +} + +template <> +template +constexpr int S::SizeOfU(int param) const { + return param; +} + +template <> +template +constexpr int S::SizeOfT(int param) const { + return param; +} + +static_assert(S().SizeOfU() == sizeof(char), ""); +static_assert(S().SizeOfT() == sizeof(int), ""); +static_assert(S().SizeOfU() == sizeof(char), ""); +static_assert(S().SizeOfT() == sizeof(short *), ""); + +} // namespace GH68490 + +#endif diff --git a/clang/test/SemaTemplate/default-parm-init.cpp b/clang/test/SemaTemplate/default-parm-init.cpp deleted file mode 100644 index 73ba8998df6a..000000000000 --- a/clang/test/SemaTemplate/default-parm-init.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s -// expected-no-diagnostics - -namespace std { - -template class function; - -template class invoker_base { -public: - virtual ~invoker_base() { } - virtual R invoke(Args...) = 0; - virtual invoker_base* clone() = 0; -}; - -template -class functor_invoker : public invoker_base { -public: - explicit functor_invoker(const F& f) : f(f) { } - R invoke(Args... args) { return f(args...); } - functor_invoker* clone() { return new functor_invoker(f); } - -private: - F f; -}; - -template -class function { -public: - typedef R result_type; - function() : invoker (0) { } - function(const function& other) : invoker(0) { - if (other.invoker) - invoker = other.invoker->clone(); - } - - template function(const F& f) : invoker(0) { - invoker = new functor_invoker(f); - } - - ~function() { - if (invoker) - delete invoker; - } - - function& operator=(const function& other) { - function(other).swap(*this); - return *this; - } - - template - function& operator=(const F& f) { - function(f).swap(*this); - return *this; - } - - void swap(function& other) { - invoker_base* tmp = invoker; - invoker = other.invoker; - other.invoker = tmp; - } - - result_type operator()(Args... args) const { - return invoker->invoke(args...); - } - -private: - invoker_base* invoker; -}; - -} - -template -struct Problem { - template - constexpr int FuncAlign(int param = alignof(FunctionTemplateParam)); - - template - constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam)); - - template - constexpr int FuncAlign2(int param = alignof(TemplateParam)); - - template - constexpr int FuncSizeof2(int param = sizeof(TemplateParam)); -}; - -template -struct Problem { - template - constexpr int FuncAlign(int param = alignof(FunctionTemplateParam)); - - template - constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam)); - - template - constexpr int FuncAlign2(int param = alignof(TemplateParam)); - - template - constexpr int FuncSizeof2(int param = sizeof(TemplateParam)); -}; - -template -template -constexpr int Problem::FuncAlign(int param) { - return 2U*param; -} - -template -template -constexpr int Problem::FuncSizeof(int param) { - return 2U*param; -} - -template -template -constexpr int Problem::FuncAlign2(int param) { - return 2U*param; -} - -template -template -constexpr int Problem::FuncSizeof2(int param) { - return 2U*param; -} - -template <> -template -constexpr int Problem::FuncAlign(int param) { - return param; -} - -template <> -template -constexpr int Problem::FuncSizeof(int param) { - return param; -} - -template <> -template -constexpr int Problem::FuncAlign2(int param) { - return param; -} - -template <> -template -constexpr int Problem::FuncSizeof2(int param) { - return param; -} - -void foo() { - Problem p = {}; - static_assert(p.FuncAlign() == alignof(char)); - static_assert(p.FuncSizeof() == sizeof(char)); - static_assert(p.FuncAlign2() == alignof(int)); - static_assert(p.FuncSizeof2() == sizeof(int)); - Problem q = {}; - static_assert(q.FuncAlign() == 2U * alignof(char)); - static_assert(q.FuncSizeof() == 2U * sizeof(char)); - static_assert(q.FuncAlign2() == 2U *alignof(short)); - static_assert(q.FuncSizeof2() == 2U * sizeof(short)); -} - -template -class A { - public: - void run( - std::function f1 = [](auto&&) {}, - std::function f2 = [](auto&&) {}); - private: - class Helper { - public: - explicit Helper(std::function f2) : f2_(f2) {} - std::function f2_; - }; -}; - -template -void A::run(std::function f1, - std::function f2) { - Helper h(f2); -} - -struct B {}; - -int main() { - A a; - a.run([&](auto& l) {}); - return 0; -}