This is an archive of the discontinued LLVM Phabricator instance.

[flang] Restore ENUM_CLASS() to be compilation-time code
ClosedPublic

Authored by klausler on Nov 11 2022, 12:11 PM.

Details

Summary

Rework some recent changes to the ENUM_CLASS() macro so that
all of the construction of enumerator-to-name string mapping
data structures is again performed at compilation time.

Diff Detail

Event Timeline

klausler created this revision.Nov 11 2022, 12:11 PM
Herald added a project: Restricted Project. · View Herald Transcript
Herald added a subscriber: jdoerfert. · View Herald Transcript
klausler requested review of this revision.Nov 11 2022, 12:11 PM
klausler updated this revision to Diff 474833.Nov 11 2022, 12:17 PM

Update counting algorithm to get n==1 case right.

Consider this program:

#include "enum_class.h"
#include <iostream>

ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT)

int main() {
  std::cout << EnumToString(RelationalOperator::LT) << std::endl;
  std::cout << EnumToString(RelationalOperator::LE) << std::endl;
  std::cout << EnumToString(RelationalOperator::EQ) << std::endl;
  std::cout << EnumToString(RelationalOperator::NE) << std::endl;
  std::cout << EnumToString(RelationalOperator::GE) << std::endl;
  std::cout << EnumToString(RelationalOperator::GT) << std::endl;
  return 0;
}

Then compile it gcc 9.3.0

g++ flang_main.cpp -std=c++17 -g -O2 -fno-inline
gdb a.out
b enum_class.h:43
r
Breakpoint 1, Fortran::common::EnumNames<6ul> (p=0x555555555648 "LT, LE, EQ, NE, GE, GT") at enum_class.h:43
43        for (; *p; ++p) {

Is this expected?

klausler updated this revision to Diff 474911.Nov 11 2022, 6:25 PM

Convert return type to std::string_view, which is more compatible with constexpr than std::string.

Adjust a few call sites where this made a difference.

What happens if I have 2 ENUM_CLASS? You did not namespace Enum2String. There are no tests.

What happens if I have 2 ENUM_CLASS? You did not namespace Enum2String. There are no tests.

This is not a new feature, just a rework of a recent update to it. It should work as it always has.

Multiple instances of ENUM_CLASS in the same scope are distinguished by the name of the ENUM_CLASS.

EnumToString will be defined in the namespace and/or class in which the reference to the ENUM_CLASS macro appears.

What happens if I have 2 ENUM_CLASS? You did not namespace Enum2String. There are no tests.

This is not a new feature, just a rework of a recent update to it. It should work as it always has.

Multiple instances of ENUM_CLASS in the same scope are distinguished by the name of the ENUM_CLASS.

EnumToString will be defined in the namespace and/or class in which the reference to the ENUM_CLASS macro appears.

Agreed. But you could still end up with two EnumToString in the same *context*. The only difference is the type of the parameter.

ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT);
ENUM_CLASS(RelationalOperator2, LT, LE, EQ, NE, GE, GT);
klausler added a comment.EditedNov 12 2022, 11:20 AM

What happens if I have 2 ENUM_CLASS? You did not namespace Enum2String. There are no tests.

This is not a new feature, just a rework of a recent update to it. It should work as it always has.

Multiple instances of ENUM_CLASS in the same scope are distinguished by the name of the ENUM_CLASS.

EnumToString will be defined in the namespace and/or class in which the reference to the ENUM_CLASS macro appears.

Agreed. But you could still end up with two EnumToString in the same *context*. The only difference is the type of the parameter.

ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT);
ENUM_CLASS(RelationalOperator2, LT, LE, EQ, NE, GE, GT);

In that case, the difference in the parameter types is sufficient to distinguish the two functions by the usual C++ function overloading rules.

#include "enum-class.h"
#include <iostream>
ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT)
ENUM_CLASS(RelationalOperator2, LT, LE, EQ, NE, GE, GT)
int main() {
  std::cout << EnumToString(RelationalOperator::LT) << std::endl;
  std::cout << EnumToString(RelationalOperator2::LT) << std::endl;
}
LT
LT

Why do you say "Restore compile time code" in the review title? EnumToString never was compite-ime until now.

Why do you say "Restore compile time code" in the review title? EnumToString never was compite-ime until now.

I mean that the construction of the tables used by EnumToString() should now take place at compilation time rather than needing execution-time allocation and initialization.

Renaud-K accepted this revision.Nov 13 2022, 2:13 PM

Looks good.
Thank you.

This revision is now accepted and ready to land.Nov 13 2022, 2:13 PM
This revision was automatically updated to reflect the committed changes.