In order to help, I am posting the code I use to try and get a "user
constructor" FUNCTION_DECL node from a "__comp_ctor ()" FUNCTION_DECL
node as mentioned in previous emails. The code can be found at the end
of this email.
Also...
class MyClass
{
MyClass()
{}
};
int main()
{
MyClass c;
return 0;
}
This will produce at least 3 FUNCTION_DECL nodes:
1) main()
2) MyClass::MyClass(MyClass* this)
3) MyClass::__comp_ctor (MyClass* this)
I call (2) a "User Constructor" for want of a better name. But note that
BOTH (2) and (3) are considered "constructors" as returned by
DECL_CONSTRUCTOR_P(fndecl)
This comes from the fact ABI has two constructors, an in charge and an
out of charge and the orginal constructor is still there though 3 is a
clone of (2). (2) is never compiled or called.
As i understand it (2) is compiled, as that is the function that
contains the users code. I could be wrong here though as i have very
little experience hacking GCC.
The code I am using to obtain a "user constructor" FUNCTION_DECL from a
"__comp_ctor ()" FUNCTION_DECL looks as shown below. I really dont like
this code as it currently uses a strcmp in order to findwhat it is after
and it also does not work completely. I have also placed some code at
the very end of this email which is a small test case of code that this
fails for.
Thanks,
Brendon
I call the function: GetCtorEquivilent(tree fndecl) with the fndecl node
for the "__comp_ctor()" i am looking for the associated "User
constructor" for.
static tree GetCtorEqvProcMethod(tree fndecl, tree method,
const char* context_string, int context_len);
/*==================================================================*/
tree GetCtorEquivilent(tree fndecl)
{
tree context = NULL_TREE;
tree method = NULL_TREE;
int context_len = 0;
const char* context_string = NULL;
tree ret = NULL_TREE;
context = DECL_CONTEXT(fndecl);
BJC_ASSERT(TYPE_P(context), "Should be a TYPE object");
BJC_ASSERT(CLASS_TYPE_P(context), "Should be a CLASS TYPE object");
/* Get list of classes methods that we will search for a
constructor in. */
method = TYPE_METHODS(context);
context_string = IDENTIFIER_POINTER(
DECL_NAME(TYPE_NAME(context)));
context_len = strlen(context_string);
while(method)
{
ret = GetCtorEqvProcMethod(fndecl, method,
context_string, context_len);
if (ret)
{
return ret;
}
method = TREE_CHAIN(method);
}
return NULL_TREE;
}
/*==================================================================*/
static tree GetCtorEqvProcMethod(tree fndecl, tree method,
const char* context_string, int context_len)
{
tree ret = NULL_TREE;
tree list = NULL_TREE;
int decl_len = 0;
const char* decl_string = NULL;
/* We are only interested in constructors */
if (!DECL_CONSTRUCTOR_P(method))
{
return NULL_TREE;
}
/* Ensure we do not look at ourself */
if (method == fndecl)
{
return NULL_TREE;
}
/* If is a template decl then process all instanciations */
if (TREE_CODE(method) == TEMPLATE_DECL)
{
list = DECL_TEMPLATE_SPECIALIZATIONS(method);
while (list)
{
/* The TREE_VALUE should be eithre a FUNCTION_DECL
or a TEMPLATE_DECL process it recursivly. */
ret = GetCtorEqvProcMethod(fndecl, constructor,
TREE_VALUE(list), context_string, context_len);
if (ret)
{
return ret;
}
list = TREE_CHAIN(list);
}
return NULL_TREE;
}
/* Template decls are handled above, at this point we
should only ever see function decls. */
BJC_ASSERT(TREE_CODE(method) == FUNCTION_DECL, "");
/* This is dodgy there has to be a way to do this
without using string compare of the first part. I.e.
we are comparing without looking at the template data.*/
/* I.e. ::Container<::int>::Container() is the correct
constructor NOT
::Container<::int>::Container<::int>() which will never occur
*/
decl_string = IDENTIFIER_POINTER(DECL_NAME(method));
decl_len = strlen(decl_string);
if (strncmp(context_string, decl_string, decl_len))
{
/*decl has a different name than the context. */
return NULL_TREE;
}
if (context_len != decl_len)
{
if (context_string[decl_len] != '<')
{
/*decl has a different name than the context. */
return NULL_TREE;
}
}
/* Got a method with the same name as the class that
encapsulates it. Now checking parameter types to see if
they are the same */
/* This function is defined elsewhere and will compare
parameters of functions/methods ignoring the
in_charge_identifier, vtt_parm_identifier nodes
if the 3rd arg is true*/
if (!FunctionsHaveSameArgs(fndecl, method, true))
{
return NULL_TREE;
}
return method;
}
---------------
This is a simple test case which causes the above to fail to find a
"user constructor" for the associated "__comp_ctor() constructor". It
can probably get even simpler, but it should demonstrate the problem.
template<typename CharT>
class Traits
{
};
template<typename CharT>
class Alloc
{
};
template<typename _CharT, typename _Traits, typename _Alloc>
class MyClassT
{
public:
template<class _InputIterator>
MyClassT(_InputIterator __beg, _InputIterator __end, const
_Alloc& __a = _Alloc());
};
typedef MyClassT<char, Traits<char>, Alloc<char> > MyClass;
int main()
{
const char* str1 = "Hello1";
const char* str2 = "Hello2";
Alloc<char> a;
MyClass mc(str1, str2, a);
return 0;
}