IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an
email to Administrator. User accounts are meant only to access repo
and report issues and/or generate pull requests.
This is a purpose-specific Git hosting for
BaseALT
projects. Thank you for your understanding!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
This allows to find an existing function template instance even based on only
the template name (of course, in this case, no instantiation is done, only already
existing ones can be returned).
This allows add there same features to TListOfFunctions::FindObject and
TViewAllPublicFunctions::FindObject.
TClassEdit::ResolveTypedef was not properly handling the leading const
if there is a namespace in the name (and no template).
Transform::GetPartiallyDesugaredType was not keeping the 'const' in case
the target of the typedef was in the global scope (for example being a
fundamental type).
This fixes ROOT-5576
As the other findFunction*, findAnyFunction does not
(yet?) instantiate the function template if has not
yet been instantiated.
Also add test for findAnyFunction.
For example:
namespace edm {
template <int I> class Hash {};
const int typeN =1;
typedef Hash<typeN> ParentageID;
}
edm::ParentageID should be desugared to edm::Hash<1>.
When the machine code was generated the JIT retains a lock to the global values
so they don't go out of sync. In the cases of circular references like:
int g();
int f() {g();}
int g() {f();}
we cannot count on the removal order to get rid of the uses. We need to use the
replaceAllUsesWith. This is however tricky because the JIT already generated the
code for f and g and it doesn't make sense to replace anything with anything else.
Thus in order to support that we need to hack one of the JIT callbacks which
prevents the replace of values of already emitted code.
The compiled code is unloaded by iterating the AST out of which the compiled code
came. The problem is that C++ supports static initialization. For example:
int a = 5; on the global scope means set the value of a to 5 before the program
starts. To support that clang implicitly generates functions that enforce the
expected initialization order. That can become easily very complex. Let's see
a more "real-life" example:
int f() { printf("I am f()"); return 0; }
int a = f();
Besides the code for a and f clang will emit:
define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
entry:
%0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%"struct.cling::runtime::internal::__trigger__cxa_atexit"*)* @_ZN5cling7runtime8internal21__trigger__cxa_atexitD1Ev to void (i8*)*), i8* getelementptr inbounds (%"struct.cling::runtime::internal::__trigger__cxa_atexit"* @_ZN5cling7runtime8internal1SE, i32 0, i32 0), i8* @__dso_handle) #1
ret void
}
define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
entry:
call void @__cxx_global_var_init()
ret void
}
and more importantly:
define internal void @__cxx_global_var_init1() section "__TEXT,__StaticInit,regular,pure_instructions" {
entry:
%call = call i32 @_Z1fv() ; THAT IS A REFERENCE TO f()
store i32 %call, i32* undef, align 4
ret void
}
So when iterating the AST and trying to remove f(), we cannot because it is still
referenced by __cxx_global_var_init1. However we know this is not an issue,
because that __cxx_global_var_init1 was meant to be executed only once and that
already happened. So in first approximation we could drop the references of f
in __cxx_global_var_init1 and remove the rest.