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;
        }

Reply via email to