Skip to content

Commit

Permalink
Merge pull request #392 from andreasfertig/fixIssue391
Browse files Browse the repository at this point in the history
Fixed #391: Placement of `final` was wrong for a class template.
  • Loading branch information
andreasfertig authored Mar 27, 2021
2 parents 79a56a4 + 18e1387 commit ba63e91
Show file tree
Hide file tree
Showing 11 changed files with 424 additions and 13 deletions.
8 changes: 4 additions & 4 deletions CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2651,6 +2651,10 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)

mOutputFormatHelper.Append(GetName(*stmt));

if(classTemplateSpecializationDecl) {
InsertTemplateArgs(*classTemplateSpecializationDecl);
}

if(stmt->hasAttr<FinalAttr>()) {
mOutputFormatHelper.Append(" final");
}
Expand All @@ -2661,10 +2665,6 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)
return;
}

if(classTemplateSpecializationDecl) {
InsertTemplateArgs(*classTemplateSpecializationDecl);
}

if(stmt->getNumBases()) {
mOutputFormatHelper.Append(" : ");

Expand Down
3 changes: 3 additions & 0 deletions InsightsHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,9 @@ std::string GetTypeNameAsParameter(const QualType& t, const std::string& varName
typeName += StrCat(" ", varName);
}

} else if(isa<MemberPointerType>(t)) {
InsertAfter(typeName, "::*", varName);

} else if(isPointerToArray) {
if(Contains(typeName, "(*")) {
InsertAfter(typeName, "(*", varName);
Expand Down
11 changes: 11 additions & 0 deletions tests/Final2Test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
template<typename T>
class FinalTest final
{
};


int main()
{
FinalTest<int> a{};
}

22 changes: 22 additions & 0 deletions tests/Final2Test.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
template<typename T>
class FinalTest final
{
};

/* First instantiated from: Final2Test.cpp:9 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class FinalTest<int> final
{
};

#endif



int main()
{
FinalTest<int> a = {};
}


12 changes: 6 additions & 6 deletions tests/Issue374.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ struct S;

struct T
{
int S::* s_mptr;
int T::* t_mptr;
int S::*s_mptr;
int T::*t_mptr;
using MemberVarPtr_7 = int T::*;
static MemberVarPtr_7 static_mptr;
template<int S::* >
Expand All @@ -16,12 +16,12 @@ struct T
void f();
struct N
{
int S::* s_mptr;
int T::* t_mptr;
int N::* n_mptr;
int S::*s_mptr;
int T::*t_mptr;
int N::*n_mptr;
};

int N::* n_mptr;
int N::*n_mptr;
};


Expand Down
101 changes: 101 additions & 0 deletions tests/Issue391.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// cmdline:-std=c++2a
#include <functional>
#include <iostream>

namespace tnt
{
template <typename T>
[[nodiscard]] constexpr std::string_view type_name() noexcept
{
// thx Boost.UT authors
// https://github.com/boost-ext/ut/blob/3b05dca6a629497910cf8e92aebcaead0124c8b4/include/boost/ut.hpp#L228
#if defined(_MSC_VER) and not defined(__clang__)
return {__FUNCSIG__ + 89, sizeof(__FUNCSIG__) - 106};
#elif defined(__clang__)
return {__PRETTY_FUNCTION__ + 39, sizeof(__PRETTY_FUNCTION__) - 41};
#elif defined(__GNUC__)
return {__PRETTY_FUNCTION__ + 54, sizeof(__PRETTY_FUNCTION__) - 105};
#endif
}

template <auto A>
[[nodiscard]] constexpr std::string_view value_name() noexcept
{
// thx Boost.UT authors
// https://github.com/boost-ext/ut/blob/3b05dca6a629497910cf8e92aebcaead0124c8b4/include/boost/ut.hpp#L228
#if defined(_MSC_VER) and not defined(__clang__)
return {__FUNCSIG__ + 89, sizeof(__FUNCSIG__) - 106};
#elif defined(__clang__)
return {__PRETTY_FUNCTION__ + 40, sizeof(__PRETTY_FUNCTION__) - 42};
#elif defined(__GNUC__)
return {__PRETTY_FUNCTION__ + 60, sizeof(__PRETTY_FUNCTION__) - 111};
#endif
}

template <typename>
struct wrapper;

template <typename T>
struct printer final
{
explicit constexpr printer(T const& ref) noexcept
: data{std::addressof(ref)} {}

printer(T const&&) = delete;

template <typename R, typename... Args>
void operator()(std::string_view name, R (T::*ptr)(Args...))
{
std::cout << "\t" << type_name<R>() << ' ' << name << " = " << std::invoke(ptr, data) << ";\n";
}

template <typename R>
void operator()(std::string_view name, R T::*ptr)
{
std::cout << "\t" << type_name<R>() << ' ' << name << " = " << std::invoke(ptr, data) << ";\n";
}

private:
const T* data;
};

template <typename T>
requires requires { &tnt::wrapper<T>::template operator()<printer<T>>; }
struct serializer final
{
template <typename Vis>
static constexpr void get_visit(Vis &&vis)
{
wrap(std::forward<Vis>(vis));
}

static constexpr wrapper<T> wrap;
};
}

struct my_type final
{
int a;
std::string_view b;
};

template <>
struct tnt::wrapper<my_type> final
{
template <typename Vis>
constexpr void operator ()(Vis &&vis) const
{
vis("a", &my_type::a);
vis("b", &my_type::b);
}
};

int main()
{
constexpr my_type t{.a = 10, .b = "42"};
std::cout << "struct " << tnt::type_name<my_type>() << " "
<< (std::is_final_v<my_type> ? "final" : "") << "\n{\n";
tnt::printer<my_type> p{t};
tnt::serializer<my_type>::get_visit(p);
std::cout << "};\n";
}
194 changes: 194 additions & 0 deletions tests/Issue391.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// cmdline:-std=c++2a
#include <functional>
#include <iostream>

namespace tnt
{
template<typename T>
[[nodiscard("")]] inline constexpr std::basic_string_view<char, std::char_traits<char> > type_name() noexcept
{
return {__PRETTY_FUNCTION__ + 39, sizeof(__PRETTY_FUNCTION__) - 41};
}

/* First instantiated from: Issue391.cpp:96 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
[[nodiscard("")]] inline constexpr std::basic_string_view<char, std::char_traits<char> > type_name<my_type>() noexcept
{
return std::basic_string_view<char, std::char_traits<char> >{"std::string_view tnt::type_name() [T = my_type]" + 39, sizeof("std::string_view tnt::type_name() [T = my_type]") - 41};
}
#endif


/* First instantiated from: Issue391.cpp:55 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
[[nodiscard("")]] inline constexpr std::basic_string_view<char, std::char_traits<char> > type_name<int>() noexcept
{
return std::basic_string_view<char, std::char_traits<char> >{"std::string_view tnt::type_name() [T = int]" + 39, sizeof("std::string_view tnt::type_name() [T = int]") - 41};
}
#endif


/* First instantiated from: Issue391.cpp:55 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
[[nodiscard("")]] inline constexpr std::basic_string_view<char, std::char_traits<char> > type_name<std::basic_string_view<char, std::char_traits<char> > >() noexcept
{
return std::basic_string_view<char, std::char_traits<char> >{"std::string_view tnt::type_name() [T = std::__1::basic_string_view<char, std::__1::char_traits<char> >]" + 39, sizeof("std::string_view tnt::type_name() [T = std::__1::basic_string_view<char, std::__1::char_traits<char> >]") - 41};
}
#endif

template<auto A>
[[nodiscard("")]] inline constexpr std::basic_string_view<char, std::char_traits<char> > value_name() noexcept
{
return {__PRETTY_FUNCTION__ + 40, sizeof(__PRETTY_FUNCTION__) - 42};
}
template<typename type_parameter_0_0>
struct wrapper;
template<typename T>
struct printer final
{
inline explicit constexpr printer(const T & ref) noexcept
: data{std::addressof(ref)}
{
}

// inline printer(const T &&) = delete;
template<typename R, typename ... Args>
inline void operator()(std::basic_string_view<char, std::char_traits<char> > name, R (T::*ptr)(Args...))
{
(((((std::operator<<(std::cout, "\t") << type_name<R>()) << ' ') << name) << " = ") << std::invoke(ptr, this->data)) << ";\n";
}
template<typename R>
inline void operator()(std::basic_string_view<char, std::char_traits<char> > name, R T::*ptr)
{
(((((std::operator<<(std::cout, "\t") << type_name<R>()) << ' ') << name) << " = ") << std::invoke(ptr, this->data)) << ";\n";
}

private:
const T * data;
};

/* First instantiated from: Issue391.cpp:98 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct printer<my_type> final
{
inline explicit constexpr printer(const my_type & ref) noexcept
: data{std::addressof(ref)}
{
}

// inline printer(const my_type &&) = delete;
template<typename R, typename ... Args>
inline void operator()(std::basic_string_view<char, std::char_traits<char> > name, R (my_type::*ptr)(Args...));
template<typename R>
inline void operator()(std::basic_string_view<char, std::char_traits<char> > name, R my_type::*ptr);

/* First instantiated from: Issue391.cpp:88 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline void operator()<int>(std::basic_string_view<char, std::char_traits<char> > name, int my_type::*ptr)
{
std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::cout, "\t"), type_name<int>()), ' '), std::basic_string_view<char, std::char_traits<char> >(name)), " = ").operator<<(std::invoke(ptr, this->data)), ";\n");
}
#endif


/* First instantiated from: Issue391.cpp:89 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline void operator()<std::basic_string_view<char, std::char_traits<char> > >(std::basic_string_view<char, std::char_traits<char> > name, std::basic_string_view<char, std::char_traits<char> > my_type::*ptr)
{
std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::cout, "\t"), type_name<std::basic_string_view<char, std::char_traits<char> > >()), ' '), std::basic_string_view<char, std::char_traits<char> >(name)), " = "), std::basic_string_view<char, std::char_traits<char> >(std::invoke(ptr, this->data))), ";\n");
}
#endif


private:
const my_type * data;
public:
};

#endif
template<typename T>
requires requires{
&wrapper<T>::template operator()<printer<T> >;
}
struct serializer final
{
template<typename Vis>
static inline constexpr void get_visit(Vis && vis)
{
wrap(std::forward<Vis>(vis));
}
inline static constexpr const wrapper<T> wrap;
};

/* First instantiated from: Issue391.cpp:99 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct serializer<my_type> final
{
template<typename Vis>
static inline constexpr void get_visit(Vis && vis);

/* First instantiated from: Issue391.cpp:99 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
static inline constexpr void get_visit<printer<my_type> &>(printer<my_type> & vis)
{
wrap.operator()(std::forward<printer<my_type> &>(vis));
}
#endif

inline static constexpr const wrapper<my_type> wrap = wrapper<my_type>();
};

#endif

}

struct my_type final
{
int a;
std::basic_string_view<char, std::char_traits<char> > b;
};



template<>
struct tnt::wrapper<my_type> final
{
template<typename Vis>
inline constexpr void operator()(Vis && vis) const
{
vis("a", &my_type::a);
vis("b", &my_type::b);
}

/* First instantiated from: Issue391.cpp:69 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline constexpr void operator()<tnt::printer<my_type> &>(tnt::printer<my_type> & vis) const
{
vis.operator()(std::basic_string_view<char, std::char_traits<char> >("a"), &my_type::a);
vis.operator()(std::basic_string_view<char, std::char_traits<char> >("b"), &my_type::b);
}
#endif

// inline constexpr tnt::wrapper() noexcept = default;
};



int main()
{
constexpr const my_type t = {10, std::basic_string_view<char, std::char_traits<char> >("42")};
std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::operator<<(std::cout, "struct "), tnt::type_name<my_type>()), " "), (std::is_final_v<my_type> ? "final" : "")), "\n{\n");
tnt::printer<my_type> p = tnt::printer<my_type>{t};
tnt::serializer<my_type>::get_visit(p);
std::operator<<(std::cout, "};\n");
}

Loading

0 comments on commit ba63e91

Please sign in to comment.