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!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
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.
When we dectect that the last expression is a record type and is not
a temporary, we now return it by reference, hence avoiding an unnecessary
and sometimes impossible (cout) copy. If it is a temporary we still
return a 'copy'.
GetPartiallyDesugaredType was 'forgetting' to add full qualification of the
template parameters in some case (where the template paramter in the
QualType was not yet an elaborated type). Extend the internal interface to
distinguish when we need to add full qualification to the type itself or its
template parameters.
Add new overload for findFunctionProto and matchFunctionProto which rather than
taking the list of argument types as a StringRef, take it as a
const llvm::SmallVector<clang::QualType, 4>. This avoids the (permanent)
allocations inside clang due to the Parsing of types.
The new call is:
const clang::FunctionDecl* matchFunctionProto(const clang::Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcProto,
bool objectIsConst
) const;
and the function must match in name and prototype (including constness).
The only thing not checked is the actual declaration context.