I’m porting very old code to ROOT6 that uses #pragma conversion directives as described in the Users Guide in section 11.5.6.1 . The underlying code unfortunately uses the word “Root” as a class name which causes Cling ( TSchemaHelper ) to complain that the name is ambiguous . It looks like namespace Root becomes namespace ROOT in the dictionary file.
Is this implicit capitilization a bug or a feature ? ROOT5 never had a problem with it . Changing the underlying code will cause a lot of pain.
Philippe,
The code is very old and and most classes derive from a class called RAT::DS::Root . Not suere why that name was chosen but whatever. The problem with ROOT6 and cling happens with #pragma lines in the LinkDef file like :
build/linuxx8664gcc/RAT_Dict.C:1321:7: error: reference to ‘ROOT’ is ambiguous
ROOT::Internal::TSchemaHelper* rule;
^~~~
build/linuxx8664gcc/RAT_Dict.C:197:14: note: candidates are: ‘namespace RAT::ROOT { }’
namespace ROOT {
^~~~
In file included from /usr/local/root_v6.22_00/include/TObject.h:17,
from /usr/local/root_v6.22_00/include/TNamed.h:25,
from /usr/local/root_v6.22_00/include/TDictionary.h:44,
from /usr/local/root_v6.22_00/include/TClass.h:23,
from build/linuxx8664gcc/RAT_Dict.C:14:
/usr/local/root_v6.22_00/include/Rtypes.h:103:11: note: ‘namespace ROOT { }’
namespace ROOT {
^~~~
build/linuxx8664gcc/RAT_Dict.C:1321:38: error: ‘rule’ was not declared in this scope
ROOT::Internal::TSchemaHelper* rule;
^~~~
.....
Ok. So we need to figure what is changing RAT::Root into RAT::ROOT … a priori this does not come from our code. I suspect somewhere there is a #defined Root ROOT …
To figure out you should be able to grab the command line that compiles RAT_Dict.C, replace the -o with a -E (and the RAT_Dict.o into RAT_Dict.E) and this should contains all the code that the compiler sees. From there we can find where namespace RAT::ROOT is declare directly or indirectly …
There is no #defined Root anywhere. And the only place where the namespace and Root occurs in the same line in the .E file is :
namespace RAT{namespace DS{class attribute((annotate("$clingAutoload$RAT/DS/Root.hh"))) Root;}}
There is a “fix” though - if I hack the generated .C file and change lines like ROOT::TSchemaHelper *rule into ::ROOT::TSchemaHelper *rule etc. everything compiles fine.
It is almost like g++ is case insensitive when it comes to namespaces.
build/linuxx8664gcc/RAT_Dict.C: In function ‘ROOT::TGenericClassInfo* ROOT::GenerateInitInstanceLocal(const RAT::DS::QT*)’:
build/linuxx8664gcc/RAT_Dict.C:966:7: error: reference to ‘ROOT’ is ambiguous
ROOT::Internal::TSchemaHelper* rule;
^~~~
build/linuxx8664gcc/RAT_Dict.C:197:14: note: candidates are: ‘namespace RAT::ROOT { }’
namespace ROOT {
^~~~
In file included from /usr/local/root_v6.22_08/include/TObject.h:17,
from /usr/local/root_v6.22_08/include/TNamed.h:25,
from /usr/local/root_v6.22_08/include/TDictionary.h:44,
from /usr/local/root_v6.22_08/include/TClass.h:23,
from build/linuxx8664gcc/RAT_Dict.C:14:
/usr/local/root_v6.22_08/include/Rtypes.h:103:11: note: ‘namespace ROOT { }’
namespace ROOT {
^~~~
build/linuxx8664gcc/RAT_Dict.C:966:38: error: ‘rule’ was not declared in this scope
ROOT::Internal::TSchemaHelper* rule;
^~~~
build/linuxx8664gcc/RAT_Dict.C:966:38: note: suggested alternative: ‘null’
ROOT::Internal::TSchemaHelper* rule;
^~~~
null
build/linuxx8664gcc/RAT_Dict.C:969:48: error: template argument 1 is invalid
std::vector<ROOT::Internal::TSchemaHelper> readrules(1);
^
build/linuxx8664gcc/RAT_Dict.C:969:48: error: template argument 2 is invalid
build/linuxx8664gcc/RAT_Dict.C:970:26: error: invalid types ‘int[int]’ for array subscript
rule = &readrules[0];
^
build/linuxx8664gcc/RAT_Dict.C:977:40: error: no matching function for call to ‘ROOT::TGenericClassInfo::SetReadRules(int&)’
instance.SetReadRules( readrules );
^
In file included from /usr/local/root_v6.22_08/include/Rtypes.h:189,
from /usr/local/root_v6.22_08/include/TObject.h:17,
from /usr/local/root_v6.22_08/include/TNamed.h:25,
from /usr/local/root_v6.22_08/include/TDictionary.h:44,
from /usr/local/root_v6.22_08/include/TClass.h:23,
from build/linuxx8664gcc/RAT_Dict.C:14:
/usr/local/root_v6.22_08/include/TGenericClassInfo.h:137:41: note: candidate: ‘void ROOT::TGenericClassInfo::SetReadRules(const std::vector<ROOT::Internal::TS
chemaHelper>&)’
void SetReadRules( const std::vector<ROOT::Internal::TSchemaHelper>& rules );
^~~~~~~~~~~~
/usr/local/root_v6.22_08/include/TGenericClassInfo.h:137:41: note: no known conversion for argument 1 from ‘int’ to ‘const std::vector<ROOT::Internal::TSche
maHelper>&’
humm … to make progress can you send me enough of your header files to reproduce this problem (and/or complete instruction to download and build the full software)
That would be difficult and take a while. What triggers this is the #pragma statement in the LinkDef file. If I take it out evertyhing is fine . Adding it triggers the ROOT::Internal::TSchemaHe // Function generating the singleton type initializer
That is a reasonable change and is necessary/consistent.
However, I would like to understand why this is happening in your case but not elsewhere, I am concerned that there is a more subtle issue … and at the very least I want to add a test representing your use case (or more exactly that leads it to trigger this issue) to avoid breaking it in future code changes.
The casing ROOT vs Root was a fun but irrelevant sidetrack (both the compiler and ROOT are case sensitive ).
The underlying problems (a namespace RAT::ROOT within the code generated by rootcling) is solved in the master. I will backport it this to v6.22. I will also, for good measure, apply your suggestion.
The trigger is the fact that one your headers (src/daq/SCBProc.hh) contains:
using namespace RAT;
triggering the confusion that we rarely see elsewhere.
And removing this line and making a couple or so minor related changes solve the problem with the version of ROOT you are using (see the updated code on falcon).
Cheers,
Philippe.
PS. Unless you are generating your documentation with THtml, the ClassImp macros can be removed.