lock3 / meta

122 stars 11 forks source link

Reflection on Members After TreeTransform #22

Closed l3bot closed 4 years ago

l3bot commented 4 years ago

In GitLab by @sdgoodrick on Aug 14, 2018, 12:03

If we have a dependent member expression (applies to both variables and functions), then it will be parsed as an UnresolvedLookupExpr that has to be transformed by TreeTransform::TransformUnresolvedLookupExpr. During this transformation, there are about 6 million checks for whether or not a member is called without an object, making it very hard to circumvent. As such, only static dependent members can be reflected on at this time. Fix this.

ex:

template<typename T>
struct S1 {
  constexpr T foo() { return T(); }
  constexpr T variable;
};

template<typename T>
constexpr int bar() {
  constexpr meta::info x6 = reflexpr(S1<T>::foo);
  constexpr meta::info x7 = reflexpr(S1<T>::variable);
}

int main() {
  constexpr int x = bar<int>();
}

This is an error unless foo() and variable are static.

l3bot commented 4 years ago

In GitLab by @sdgoodrick on Aug 15, 2018, 15:15

Recent commit almost fixes this issue. constexpr meta::info x = reflexpr(S1<T>::variable); now compiles and prints without issue.

However, a new issue with: constexpr meta::info x = reflexpr(S1<T>::function); has arisen. It gives the error:

constexpr variable 'x' must be initialized by a constant expression

See the test this affects: https://gitlab.com/lock3/clang/blob/reflect-sdg/test/CXX/meta/reflexpr_dependent.cpp

Code that is likely causing this can be found in TreeTransform::TransformCXXReflectExpr (final case / UnresolvedLookupExpr, TreeTransform.h:7262)

l3bot commented 4 years ago

In GitLab by @sdgoodrick on Aug 16, 2018, 12:34

The problem was that the body of the function was not getting transformed and instantiated. I don't know why this did not result in an assertion, but whatever.

I've tried to instantiate the body in two ways: first calling TransformStmt() on Decl::getBody(). This did absolutely nothing; the body was still uninstantiated after its call.

Second, I tried calling TransformDefinition on the body. This also turned out to be wrong, since it appears TransformDefinition only transforms template specializations. I don't know why they didn't call it TransformTemplateSpecialization.

l3bot commented 4 years ago

In GitLab by @DarkArc on Apr 18, 2019, 14:51

changed the description

l3bot commented 4 years ago

In GitLab by @DarkArc on Apr 25, 2019, 16:02

I don't think there's an issue here anymore. I tested with the following code and found no problems:

#include <experimental/meta>

using namespace std::experimental;

template<typename T>
struct S1 {
  T foo() { return T(); }
  T variable;
};

template<typename T>
constexpr int bar() {
  constexpr meta::info x6 = reflexpr(S1<T>::foo);
  constexpr meta::info x7 = reflexpr(S1<T>::variable);

  return 0;
}

int main() {
  constexpr int x = bar<int>();
}
l3bot commented 4 years ago

In GitLab by @DarkArc on Apr 25, 2019, 16:02

closed