News:

As usual while waiting for the next release - don't forget to check the nightly builds in the forum.

Main Menu

Auto-completion of functions pointers in a structure

Started by Folco, May 17, 2010, 06:35:10 PM

Previous topic - Next topic

Folco

Hi all,

I use a structure defined like that :
typedef struct
{
    int (*Load)();          /* Constructor */
    void (*Unload)();       /* Destructor */
    void (*Manage)();       /* Management handler */
    MODULE_DATA* Data;      /* Used data */
} MODULE;

When typing to write inside members of this structure, only the 'Data' member is displayed in the auto-completion list :



Is it a bug, must I fill a bug report ? Or perhaps I am wrong ?

Infos :
Code::Blocks svn 6218 on Debian Lenny 32 bits.
Package provided by Jens.

BTW : Many thanks, Jens, for your work and for the repo often updated !!!  8)
Kernel Extremist - PedroM power ©

reckless

not sure its a bug since you allready have the other members declared it correctly shows the missing one.

what happens if you remove Load Data etc from (*ModuleList[*ModuleNum]). ?

ollydbg

Quote from: Folco on May 17, 2010, 06:35:10 PM
Hi all,

I use a structure defined like that :
typedef struct
{
    int (*Load)();          /* Constructor */
    void (*Unload)();       /* Destructor */
    void (*Manage)();       /* Management handler */
    MODULE_DATA* Data;      /* Used data */
} MODULE;



I just do a test, and find that only "Data" will be parsed as a member of this structure. (All the other function pointers were not correctly parsed.)
So, only this member get prompted.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Folco

Quotewhat happens if you remove Load Data etc from (*ModuleList[*ModuleNum]). ?
Exactly the same behavior.
QuoteAll the other function pointers were not correctly parsed.
So it's should be a bug, and I should fill a bug report ?
Kernel Extremist - PedroM power ©

reckless

id probably have to say yes as that shouldnt happen.

ollydbg

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

#6
The test code is "test.h" under ParserTest project. (I'm using the latest CC_branch)

typedef struct
{
   int (*Load)();          /* Constructor */
   void (*Unload)();       /* Destructor */
   void (*Manage)();       /* Management handler */
   MODULE_DATA* Data;      /* Used data */
} MODULE;


And here is the log out put:
Quote
--------------M-a-i-n--L-o-g--------------

000001. Parse() : Parsing ''
000002. InitTokenizer() : m_Filename='test.h', m_FileSize=226.
000003. Init() : m_Filename='test.h'
000004. DoParse() : Loop:m_Str='', token='typedef'
000005. HandleTypedef() : Typedef start
000006. HandleTypedef() : token=struct, peek={
000007. HandleTypedef() : Before HandleClass m_LastUnnamedTokenName=''
000008. HandleClass() : Found class '{'
000009. DoAddToken() : Created token='UnnamedStruct0', file_idx=1, line=1
000010. GetActualTokenType() : Searching within m_Str=''
000011. GetActualTokenType() : Compensated m_Str=''
000012. GetActualTokenType() : Returning ''
000013. DoAddToken() : Prepending ''
000014. DoAddToken() : Added/updated token 'UnnamedStruct0' (0), type '', actual ''. Parent is  (-1)
000015. DoParse() : Loop:m_Str='', token='int'
000016. wxString Tokenizer::ReadBlock(const wxChar&) : line=3, CurrentChar='(', PreviousChar=' ', NextChar='*', leftBrace(()
000017. ReadBlock(): (END) We are now at line 3, CurrentChar='(', PreviousChar=')', NextChar=')'
000018. wxString Tokenizer::ReadBlock(const wxChar&) : line=3, CurrentChar='(', PreviousChar=')', NextChar=')', leftBrace(()
000019. ReadBlock(): (END) We are now at line 3, CurrentChar=';', PreviousChar=')', NextChar=' '
000020. DoParse() : Loop:m_Str='int(*Load)', token='()'
000021. DoParse() : Loop:m_Str='int(*Load)', token=';'
000022. DoParse() : Loop:m_Str='', token='void'
000023. wxString Tokenizer::ReadBlock(const wxChar&) : line=4, CurrentChar='(', PreviousChar=' ', NextChar='*', leftBrace(()
000024. ReadBlock(): (END) We are now at line 4, CurrentChar='(', PreviousChar=')', NextChar=')'
000025. wxString Tokenizer::ReadBlock(const wxChar&) : line=4, CurrentChar='(', PreviousChar=')', NextChar=')', leftBrace(()
000026. ReadBlock(): (END) We are now at line 4, CurrentChar=';', PreviousChar=')', NextChar=' '
000027. DoParse() : Loop:m_Str='void(*Unload)', token='()'
000028. DoParse() : Loop:m_Str='void(*Unload)', token=';'
000029. DoParse() : Loop:m_Str='', token='void'
000030. wxString Tokenizer::ReadBlock(const wxChar&) : line=5, CurrentChar='(', PreviousChar=' ', NextChar='*', leftBrace(()
000031. ReadBlock(): (END) We are now at line 5, CurrentChar='(', PreviousChar=')', NextChar=')'
000032. wxString Tokenizer::ReadBlock(const wxChar&) : line=5, CurrentChar='(', PreviousChar=')', NextChar=')', leftBrace(()
000033. ReadBlock(): (END) We are now at line 5, CurrentChar=';', PreviousChar=')', NextChar=' '
000034. DoParse() : Loop:m_Str='void(*Manage)', token='()'
000035. DoParse() : Loop:m_Str='void(*Manage)', token=';'
000036. DoParse() : Loop:m_Str='', token='MODULE_DATA'
000037. DoParse() : Loop:m_Str='MODULE_DATA ', token='*'
000038. DoParse() : Loop:m_Str='MODULE_DATA ', token='Data'
000039. DoAddToken() : Created token='Data', file_idx=1, line=6
000040. GetActualTokenType() : Searching within m_Str='MODULE_DATA'
000041. GetActualTokenType() : Compensated m_Str='MODULE_DATA'
000042. GetActualTokenType() : Found 'MODULE_DATA'
000043. DoAddToken() : Prepending ''
000044. DoAddToken() : Added/updated token 'Data' (1), type 'MODULE_DATA*', actual 'MODULE_DATA'. Parent is UnnamedStruct0 (0)
000045. DoParse() : Loop:m_Str='MODULE_DATA', token=';'
000046. DoParse() : Loop:m_Str='', token='}'
000047. ReadClsNames() : Adding variable 'MODULE' as '' to '<no-parent>'
000048. DoAddToken() : Created token='MODULE', file_idx=1, line=7
000049. GetActualTokenType() : Searching within m_Str='UnnamedStruct0'
000050. GetActualTokenType() : Compensated m_Str='UnnamedStruct0'
000051. GetActualTokenType() : Found 'UnnamedStruct0'
000052. DoAddToken() : Prepending ''
000053. DoAddToken() : Added/updated token 'MODULE' (2), type 'UnnamedStruct0', actual 'UnnamedStruct0'. Parent is  (-1)
000054. HandleTypedef() : After HandleClass m_LastUnnamedTokenName='UnnamedStruct0'
000055. HandleTypedef() : Pushing component='UnnamedStruct0', typedef args=''
000056.  + 'UnnamedStruct0'
000057. HandleTypedef() : token=;, peek=
000058. HandleTypedef() : Typedef done


--------------T-r-e-e--L-o-g--------------

000059. +class UnnamedStruct0 {...}   [1,1]
000060. MODULE_DATA* UnnamedStruct0::Data   [6,0]
000061. typedef UnnamedStruct0 MODULE   [7,0]


--------------L-i-s-t--L-o-g--------------

000062. class class UnnamedStruct0 {...}   [1,1]
000063. variable MODULE_DATA* UnnamedStruct0::Data   [6,0]
000064. typedef typedef UnnamedStruct0 MODULE   [7,0]


So, you can see, the final "List log", there are only three Tokens found.  :D


Edit

Haha, I find the bug, it seems the function pointer declaration is just something like:

AAA (*BBB) ()

See the screen shot of my debugger.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

ollydbg

#7
Ok, solved by change the code (just comment some lines , :D)

               if (   (peek.GetChar(0) == '(')
                   && m_Options.handleFunctions
                   && m_Str.IsEmpty()
                   && m_EncounteredNamespaces.empty()
                   && m_EncounteredTypeNamespaces.empty()
                   && (!m_pLastParent || m_pLastParent->m_Name != token) ) // if func has same name as current scope (class)
               {
                   int id = m_pTokensTree->TokenExists(token, -1, tkPreprocessor);

                   if (id != -1)
                   {
                       m_Tokenizer.GetToken();
                       HandleMacro(id, peek);
                       m_Str.Clear();
                   }
                   else
                   {
                       //we need to check if it is a function pointer definition here:
                       // like int (* p) ();
                       //wxString arg = m_Tokenizer.GetToken(); // eat args ()
                       m_Str = token;
                   }
               }


Here is the new log file:

--------------M-a-i-n--L-o-g--------------

000001. Parse() : Parsing ''
000002. InitTokenizer() : m_Filename='test.h', m_FileSize=226.
000003. Init() : m_Filename='test.h'
000004. DoParse() : Loop:m_Str='', token='typedef'
000005. HandleTypedef() : Typedef start
000006. HandleTypedef() : token=struct, peek={
000007. HandleTypedef() : Before HandleClass m_LastUnnamedTokenName=''
000008. HandleClass() : Found class '{'
000009. DoAddToken() : Created token='UnnamedStruct0', file_idx=1, line=1
000010. GetActualTokenType() : Searching within m_Str=''
000011. GetActualTokenType() : Compensated m_Str=''
000012. GetActualTokenType() : Returning ''
000013. DoAddToken() : Prepending ''
000014. DoAddToken() : Added/updated token 'UnnamedStruct0' (0), type '', actual ''. Parent is  (-1)
000015. DoParse() : Loop:m_Str='', token='int'
000016. wxString Tokenizer::ReadBlock(const wxChar&) : line=3, CurrentChar='(', PreviousChar=' ', NextChar='*', leftBrace(()
000017. ReadBlock(): (END) We are now at line 3, CurrentChar='(', PreviousChar=')', NextChar=')'
000018. DoParse() : Loop:m_Str='int', token='(*Load)'
000019. wxString Tokenizer::ReadBlock(const wxChar&) : line=3, CurrentChar='(', PreviousChar=')', NextChar=')', leftBrace(()
000020. ReadBlock(): (END) We are now at line 3, CurrentChar=';', PreviousChar=')', NextChar=' '
000021. HandleFunction() : Adding function '(*Load)': m_Str='int'
000022. HandleFunction() : name='(*Load)', args='()', peek=';'
000023. HandleFunction() : !(Ctor/Dtor) '(*Load)', m_Str='int', localParent='<none>'
000024. HandleFunction() : Adding function '(*Load)', ': m_Str='int', enc_ns='nil'.
000025. HandleFunction() : Add token name='(*Load)', args='()', return type='int'
000026. GetStrippedArgs() : args='()'.
000027. GetStrippedArgs() : stripped_args='()'.
000028. DoAddToken() : Created token='(*Load)', file_idx=1, line=3
000029. GetActualTokenType() : Searching within m_Str='int'
000030. GetActualTokenType() : Compensated m_Str='int'
000031. GetActualTokenType() : Found 'int'
000032. DoAddToken() : Prepending ''
000033. DoAddToken() : Added/updated token '(*Load)' (1), type 'int', actual 'int'. Parent is UnnamedStruct0 (0)
000034. DoParse() : Loop:m_Str='', token=';'
000035. DoParse() : Loop:m_Str='', token='void'
000036. wxString Tokenizer::ReadBlock(const wxChar&) : line=4, CurrentChar='(', PreviousChar=' ', NextChar='*', leftBrace(()
000037. ReadBlock(): (END) We are now at line 4, CurrentChar='(', PreviousChar=')', NextChar=')'
000038. DoParse() : Loop:m_Str='void', token='(*Unload)'
000039. wxString Tokenizer::ReadBlock(const wxChar&) : line=4, CurrentChar='(', PreviousChar=')', NextChar=')', leftBrace(()
000040. ReadBlock(): (END) We are now at line 4, CurrentChar=';', PreviousChar=')', NextChar=' '
000041. HandleFunction() : Adding function '(*Unload)': m_Str='void'
000042. HandleFunction() : name='(*Unload)', args='()', peek=';'
000043. HandleFunction() : !(Ctor/Dtor) '(*Unload)', m_Str='void', localParent='<none>'
000044. HandleFunction() : Adding function '(*Unload)', ': m_Str='void', enc_ns='nil'.
000045. HandleFunction() : Add token name='(*Unload)', args='()', return type='void'
000046. GetStrippedArgs() : args='()'.
000047. GetStrippedArgs() : stripped_args='()'.
000048. DoAddToken() : Created token='(*Unload)', file_idx=1, line=4
000049. GetActualTokenType() : Searching within m_Str='void'
000050. GetActualTokenType() : Compensated m_Str='void'
000051. GetActualTokenType() : Found 'void'
000052. DoAddToken() : Prepending ''
000053. DoAddToken() : Added/updated token '(*Unload)' (2), type 'void', actual 'void'. Parent is UnnamedStruct0 (0)
000054. DoParse() : Loop:m_Str='', token=';'
000055. DoParse() : Loop:m_Str='', token='void'
000056. wxString Tokenizer::ReadBlock(const wxChar&) : line=5, CurrentChar='(', PreviousChar=' ', NextChar='*', leftBrace(()
000057. ReadBlock(): (END) We are now at line 5, CurrentChar='(', PreviousChar=')', NextChar=')'
000058. DoParse() : Loop:m_Str='void', token='(*Manage)'
000059. wxString Tokenizer::ReadBlock(const wxChar&) : line=5, CurrentChar='(', PreviousChar=')', NextChar=')', leftBrace(()
000060. ReadBlock(): (END) We are now at line 5, CurrentChar=';', PreviousChar=')', NextChar=' '
000061. HandleFunction() : Adding function '(*Manage)': m_Str='void'
000062. HandleFunction() : name='(*Manage)', args='()', peek=';'
000063. HandleFunction() : !(Ctor/Dtor) '(*Manage)', m_Str='void', localParent='<none>'
000064. HandleFunction() : Adding function '(*Manage)', ': m_Str='void', enc_ns='nil'.
000065. HandleFunction() : Add token name='(*Manage)', args='()', return type='void'
000066. GetStrippedArgs() : args='()'.
000067. GetStrippedArgs() : stripped_args='()'.
000068. DoAddToken() : Created token='(*Manage)', file_idx=1, line=5
000069. GetActualTokenType() : Searching within m_Str='void'
000070. GetActualTokenType() : Compensated m_Str='void'
000071. GetActualTokenType() : Found 'void'
000072. DoAddToken() : Prepending ''
000073. DoAddToken() : Added/updated token '(*Manage)' (3), type 'void', actual 'void'. Parent is UnnamedStruct0 (0)
000074. DoParse() : Loop:m_Str='', token=';'
000075. DoParse() : Loop:m_Str='', token='MODULE_DATA'
000076. DoParse() : Loop:m_Str='MODULE_DATA ', token='*'
000077. DoParse() : Loop:m_Str='MODULE_DATA ', token='Data'
000078. DoAddToken() : Created token='Data', file_idx=1, line=6
000079. GetActualTokenType() : Searching within m_Str='MODULE_DATA'
000080. GetActualTokenType() : Compensated m_Str='MODULE_DATA'
000081. GetActualTokenType() : Found 'MODULE_DATA'
000082. DoAddToken() : Prepending ''
000083. DoAddToken() : Added/updated token 'Data' (4), type 'MODULE_DATA*', actual 'MODULE_DATA'. Parent is UnnamedStruct0 (0)
000084. DoParse() : Loop:m_Str='MODULE_DATA', token=';'
000085. DoParse() : Loop:m_Str='', token='}'
000086. ReadClsNames() : Adding variable 'MODULE' as '' to '<no-parent>'
000087. DoAddToken() : Created token='MODULE', file_idx=1, line=7
000088. GetActualTokenType() : Searching within m_Str='UnnamedStruct0'
000089. GetActualTokenType() : Compensated m_Str='UnnamedStruct0'
000090. GetActualTokenType() : Found 'UnnamedStruct0'
000091. DoAddToken() : Prepending ''
000092. DoAddToken() : Added/updated token 'MODULE' (5), type 'UnnamedStruct0', actual 'UnnamedStruct0'. Parent is  (-1)
000093. HandleTypedef() : After HandleClass m_LastUnnamedTokenName='UnnamedStruct0'
000094. HandleTypedef() : Pushing component='UnnamedStruct0', typedef args=''
000095.  + 'UnnamedStruct0'
000096. HandleTypedef() : token=;, peek=
000097. HandleTypedef() : Typedef done


--------------T-r-e-e--L-o-g--------------

000098. +class UnnamedStruct0 {...} [1,1]
000099. (*Load)() [3,0]
000100. (*Unload)() [4,0]
000101. (*Manage)() [5,0]
000102. MODULE_DATA* UnnamedStruct0::Data [6,0]
000103. typedef UnnamedStruct0 MODULE [7,0]


--------------L-i-s-t--L-o-g--------------

000104. class class UnnamedStruct0 {...} [1,1]
000105. function int UnnamedStruct0::(*Load)() [3,0]
000106. function void UnnamedStruct0::(*Unload)() [4,0]
000107. function void UnnamedStruct0::(*Manage)() [5,0]
000108. variable MODULE_DATA* UnnamedStruct0::Data [6,0]
000109. typedef typedef UnnamedStruct0 MODULE [7,0]



So, you can see the List Log here. It is correct now!!!

I will do more test and publish the patch here later.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

blueshake

Keep low and hear the sadness of little dog.
I fall in love with a girl,but I don't dare to tell her.What should I do?

ollydbg

Quote from: blueshake on June 27, 2010, 04:02:28 PM
will be fixed in ccbranch.

Nice, I have received your patch, And tested, here is the log:

--------------L-i-s-t--L-o-g--------------

000124. typedef typedef void(*dMessageFunction)(int errnum, const char *msg, va_list ap) [2,0]
000125. class class UnnamedStruct0 {...} [4,4]
000126. function UnnamedStruct0::Load() [6,0]
000127. function UnnamedStruct0::Unload() [7,0]
000128. function UnnamedStruct0::Manage() [8,0]
000129. variable MODULE_DATA* UnnamedStruct0::Data [9,0]
000130. typedef typedef UnnamedStruct0 MODULE [10,0]



So, after some more test, we will send to Morten, and soon it will exist in the ccbranch. :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Folco

Kernel Extremist - PedroM power ©

Folco

https://developer.berlios.de/bugs/?func=detailbug&group_id=5358&bug_id=17186 :
QuoteThis bug is fixed in the cc_branch, so can be closed.

First, many thanks for the job !

Then, what is the usual procedure ? I have to close myself the bug report, or this is an admin who have to do it ?
Kernel Extremist - PedroM power ©

ollydbg

I think admin(the developer of C::B) can do this. :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Folco

Does the fix have been imported in the main branch ?
I still get it, using C::B svn 6525 on Debian 32 bits (package by Jens, btw thank you) :

I don't know how the cc branch is handled, perhaps it hasn't been already merged in the main part of C::B ?
Kernel Extremist - PedroM power ©

oBFusCATed

(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]