root icon indicating copy to clipboard operation
root copied to clipboard

Issue with pragma enum class in template class

Open meiyasan opened this issue 1 year ago • 5 comments

Check duplicate issues.

  • [x] Checked for duplicates

Description

Hello,

I have defined an enum class type, such that I can switch between mathematical representations easily.

Considering the reproducer below, I get the following error message:

Forward declarations from [..]/install/lib/libXXX.rootmap:3:11: error: unknown type name 'MyEnum'
template <MyEnum> class MyClass;
               ^

Here is an overview of the rootmap, MyEnum is not declared

{ decls }
[..]
template <MyEnum> class MyClass;
[..]
[ libXXX.dylib ]
[...]

How can I fix the root map ? It seem enum class is missing in root map so MyEnum is not defined.

Reproducer

Here are some abstractions:

# LinkDef.h
#pragma link C++ enum class MyEnum;

#pragma link C++ class MyClass<MyEnum::E0>+;
#pragma link C++ class MyClass <MyEnum::E1>+;
#pragma link C++ class MyClass <MyEnum::E2>+;

# Header.h
enum class MyEnum { E0, E1, E2 };
template <MyEnum T = MyEnum::E0>
class MyClass : public MyClassAbstract
{
    //  [...]
}

ROOT version

v6.32.04

Installation method

build from source

Operating system

macOS 15.0

Additional context

No response

meiyasan avatar Sep 21 '24 04:09 meiyasan

Dear @xkzl ,

Thanks for your report. As a first attempt at fixing it, could you try specifying the pragma for the enum as simply

#pragma link C++ enum MyEnum;

Note the removal of the class keyword.

vepadulano avatar Sep 21 '24 07:09 vepadulano

Ciao Vincenzo,

I have tried and the root map contains now MyEnum, but at the wrong place I believe?

{ decls }
namespace ROOT { namespace XXX {  } }
template <MyEnum> class MyClass;
[...]

[ libXXX.dylib ]
# List of selected classes
[...]
# List of selected enums and outer classes
enum MyEnum
[...]

Marco

meiyasan avatar Sep 21 '24 07:09 meiyasan

Dear @xkzl ,

Indeed, I can see the same thing with the following simple example

// myheader.hxx
#ifndef myheader
#define myheader

enum class MyEnum
{
    kFirst,
    kSecond,
    kThird
};

template <MyEnum T>
class MyClass
{
};

#endif 
// LinkDef.h
#ifdef __CLING__
#pragma link C++ enum MyEnum;
#pragma link C++ class MyClass < MyEnum::kFirst> + ;
#pragma link C++ class MyClass < MyEnum::kSecond> + ;
#pragma link C++ class MyClass < MyEnum::kThird> + ;
#endif
$: rootcling -f myheaderdict.cxx myheader.hxx LinkDef.h -rmf myheader.rootmap
# myheader.rootmap
{ decls }
template <MyEnum> class MyClass;

[  ]
# List of selected classes
class MyClass<(MyEnum)0>
class MyClass<(MyEnum)1>
class MyClass<(MyEnum)2>
class MyClass<MyEnum::kFirst>
class MyClass<MyEnum::kSecond>
class MyClass<MyEnum::kThird>
# List of selected enums and outer classes
enum MyEnum

I am unsure whether we are missing some different configuration or spelling. @pcanal might be able to help here.

vepadulano avatar Sep 21 '24 09:09 vepadulano

@vepadulano did you found a fix for that ? I get spam by these "Forward declarations" messages each time I open my programs. Any fix or way to remove these messages. Except seing the error message, I couldn't find any issue in the execution of my code using MyClass

meiyasan avatar Oct 03 '24 04:10 meiyasan

@vepadulano @pcanal , I compiled a library on GCC 9 on Linux computer and received some additional warning information. Perhaps it might help, it seems to be harmless as my class seems to work as expected. I would be glad to find an alternative or a fix for that issue. Any input would be very welcome.

[  1%] Generating MyLibrary.Dict.cxx, libMyLibrary_rdict.pcm, libMyLibrary.rootmap
[  3%] Built target create_all_archives
Warning: Forward declarations of templates with enums as template parameters. The responsible class is: NonTypeTemplateParmDecl 0x7f306cb8b248 </path/to/my/sources/include/MyClass.h:69:11, col:29> col:17 referenced 'MyEnum' depth 0 index 0 T1
`-TemplateArgument expr
  `-ConstantExpr 0x7f306cb8b2a8 <col:22, col:29> 'MyEnum'
    |-value: Int 2
    `-DeclRefExpr 0x7f306cb8b208 <col:22, col:29> 'MyEnum' EnumConstant 0x7f306cb89020 'E0' 'MyEnum'

Warning: Problems with arguments for forward declaration of class MyClass
Warning: Forward declarations of templates with enums as template parameters. The responsible class is: NonTypeTemplateParmDecl 0x7f306cb8b248 </path/to/my/sources/include/MyClass.h:69:11, col:29> col:17 referenced 'MyEnum' depth 0 index 0 T1
`-TemplateArgument expr
  `-ConstantExpr 0x7f306cb8b2a8 <col:22, col:29> 'MyEnum'
    |-value: Int 2
    `-DeclRefExpr 0x7f306cb8b208 <col:22, col:29> 'MyEnum' EnumConstant 0x7f306cb89020 'E0' 'MyEnum'

Warning: Problems with arguments for forward declaration of class MyClass
Warning: Forward declarations of templates with enums as template parameters. The responsible class is: NonTypeTemplateParmDecl 0x7f306cb8b248 </path/to/my/sources/include/MyClass.h:69:11, col:29> col:17 referenced 'MyEnum' depth 0 index 0 T1
`-TemplateArgument expr
  `-ConstantExpr 0x7f306cb8b2a8 <col:22, col:29> 'MyEnum'
    |-value: Int 2
    `-DeclRefExpr 0x7f306cb8b208 <col:22, col:29> 'MyEnum' EnumConstant 0x7f306cb89020 'E0' 'MyEnum'

meiyasan avatar Oct 15 '24 07:10 meiyasan

@vepadulano @dpiparo would it be possible to advice on some fixes in a reasonable timescale ? I would be happy to contribute, but I basically have not entrypoint to start with. It makes root very unfriendly to use.

meiyasan avatar Nov 22 '24 00:11 meiyasan

At the moment the rootmap file does not support enum (nor C++20 concepts). For enums, the situations can be improved for enum class which can be forward declared (but old style enums can not be).

There is 2 solution to this problem, either move to using 'c++ module' for the dictionary containing those enums (and class template whose arguments are enum types) but this feature is still somewhat experimental. ( you will need to write a 'modulemap' file and use the options shown by rootcling --help | grep module).

The second option is to update the forward declaration writer used for the rootmap files to support enum class. (The main part is at https://github.com/root-project/root/blob/master/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.cpp)

pcanal avatar Jan 29 '25 17:01 pcanal

@pcanal Thank for your reply. This issue was resolved few weeks ago, thanks to your help on the ROOT forum. https://root-forum.cern.ch/t/issue-with-pragma-enum-class-in-template-class/62547/6

I am now relying on the cxxmodules you mentioned using -Druntime_cxxmodules=ON in my cmake. I could make module.map name dynamic using CLING_MODULEMAP_FILES customization.

Thank you.

PS: For the records, please find attached the files used to demonstrate the issue and use cxxmodules as replacement. cxxmodules.zip

meiyasan avatar Jan 29 '25 23:01 meiyasan

I just close, but of course, we can reopen if you plan to support rootmap enhancement.

meiyasan avatar Jan 29 '25 23:01 meiyasan

Hi @meiyasan, @vepadulano,

It appears this issue is closed, but wasn't yet added to a project. Please add upcoming versions that will include the fix, or 'not applicable' otherwise.

Sincerely, :robot:

github-actions[bot] avatar Jan 30 '25 06:01 github-actions[bot]