The Problem
The objects from the current directory (gDirectory) are injected into a magic scope that is available to CINT:
Important constrain: To not break old code we need to continue to support this. Of course the code is invalid C++ and thus cannot be parsed by clang. Upon clang's Sema complaining about undeclared identifiers we need to convert it into proper C++.
Use Cases
1. Simple use case:
void macro() { TFile::Open("f.root"); hpx->Draw(); }
2. Parameters
void macro() { TFile::Open("f.root"); int i = 12; obj->Func(i); }
3. Function Overloading
An additional complication is function overload resolution required in this example:
void Klass::Func(TTree*); void NameSpace::Func(TH1*); void Func(TObject*); using namespace NameSpace; void Klass::Call() { TFile::Open("f.root"); int i = 12; Func(obj); }
n. Can we have smth else?
Solutions
Escaping to Late Evaluation
In use case 1: the code can be converted to:
void macro() { TFile::Open("f.root"); Cling::Interpreter().Eval("hpx->Draw()"); }
This is now valid C++; the code hpx->Draw() will be evaluated during runtime, when we know all the necessary information. In this case we have:
In use case number 2: we need to pass the variable to the interpreter as well. We need to introduce a Context
void macro() { TFile::Open("f.root"); int i = 12; { Cling::InterpreterContext ctx; ctx.add("i", &i); Cling::Interpreter().Eval("obj->Func(i);", ctx); } }
In use case number 3: we don't know the type of obj at compile time, we don't know which overload of Func() to use.
- Here we have several options:
- Let Cling decide which overload to use - We could pass the list of candidates that Sema found during overload resolution to the escaped interpreter, probably including a copy of the identifier table. This would require changes in Sema, because the escaped Sema needs to take an external identifier table and the candidates into account;
- Assume void* - One could argue that this is a rare case. We know that unknown identifiers have to be pointers; we could simply select the void* overload of Func(), i.e. claim that obj is a void*;
- Refuse the overloads - If we have problems determining the proper overload. By refusing to accept multiple overloads we can simplify the situation;
- Discontinue Support - We could detect the case of multiple overload candidates and issue an error. This should be in case no other options are possible.
The page is based on ClingDynamicScope at tWiki