Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => CodeCompletion redesign => Topic started by: daniloz on February 11, 2011, 01:40:40 pm

Title: extern "C" not working with CC
Post by: daniloz on February 11, 2011, 01:40:40 pm
Hi All,

I have some function in assembly (on a DSP project) and I use the following syntax to declare them in C++:
Code
extern "C" void foo_asm(...);

However, the CC is not recognizing this declaration because of the ' "C" ' part... Here is a small example to reproduce this:
Code
extern "C" void  foo_asm(void);

extern void  foo_OK(void);

void main()
{
foo
}
If you place the cursor after foo in main, you just get "foo_OK" as suggestion and foo_asm doesn't even appears in the symbol browser...

Any hints or workarounds ?
Title: Re: extern "C" not working with CC
Post by: ollydbg on February 11, 2011, 02:05:01 pm
it can be fix very easily. I have see someone complain this before.
But the question is: Is it necessary???
Because currently, extern statement was skipped by CC's parser.
Title: Re: extern "C" not working with CC
Post by: daniloz on February 11, 2011, 02:20:30 pm
it can be fix very easily. I have see someone complain this before.
That's good news!

But the question is: Is it necessary???
Because currently, extern statement was skipped by CC's parser.
I don't think this is the case, if you look at my example, foo_OK is processed by the CC and shown in the Symbol Browse AND as a completion suggestion.

In my case it would be VERY convenient to have these external processed because then I can get the argument list while typing... :-)

By the way, I'd be more than happy to do the patch on my system and try it, if you point me to the right direction... ;-)
Title: Re: extern "C" not working with CC
Post by: ollydbg on February 11, 2011, 03:18:28 pm
Oh, sorry, I just review the code in "parserthread.cpp"
Code
            else if (token == ParserConsts::kw_extern)
            {
                // check for "C", "C++"
                m_Str = m_Tokenizer.GetToken();
                if (m_Str == ParserConsts::kw_C || m_Str == ParserConsts::kw_CPP)
                {
                    m_Tokenizer.GetToken(); // "eat" {
                    DoParse(); // time for recursion ;)
                }
                else
                {
                    // do nothing, just skip keyword "extern", otherwise uncomment:
                    //SkipToOneOfChars(ParserConsts::semicolon); // skip externs
                    m_Tokenizer.UngetToken();
                }
                m_Str.Clear();
            }
It seems you are right, the feature was not implemented. :D

It may be a bug, see the statement:
Code
m_Tokenizer.GetToken(); // "eat" {
I think we need to check the Token is a "{" or not, am I right?
Title: Re: extern "C" not working with CC
Post by: daniloz on February 11, 2011, 03:39:13 pm
It seems you are right, the feature was not implemented. :D
That's great news, actually... :-D

It may be a bug, see the statement:
Code
m_Tokenizer.GetToken(); // "eat" {
I think we need to check the Token is a "{" or not, am I right?
Yes, it can be a simple statement as in my example case... How do we do this check? (I am new to the CC code, sorry)

BTW, I changed by example to
Code
extern "C" {void  foo_asm(void);}

extern void  foo_OK(void);

void main()
{
foo
}
And now I get the completion for both foo_OK and foo_asm. :-)

However, I'd still prefer to not to have to use {}s...
Title: Re: extern "C" not working with CC
Post by: Loaden on February 11, 2011, 03:56:06 pm
It should been fixed in next nightly build.
Title: Re: extern "C" not working with CC
Post by: ollydbg on February 11, 2011, 03:59:50 pm
It may be a bug, see the statement:
Code
m_Tokenizer.GetToken(); // "eat" {
I think we need to check the Token is a "{" or not, am I right?
Yes, it can be a simple statement as in my example case... How do we do this check? (I am new to the CC code, sorry)
Aha, it was quite simple.

Code
// check for "C", "C++"
                m_Str = m_Tokenizer.GetToken();
                if (m_Str == ParserConsts::kw_C || m_Str == ParserConsts::kw_CPP)
                {
                    wxString a;
                    a = m_Tokenizer.PeekToken();
                    if(a=="{")
                    {
                         m_Tokenizer.GetToken(); // "eat" {
                         DoParse(); // time for recursion ;)
                    }
                    else
                    {

                          // which means it is in your case, not a "{"
                         // such as: extern "C" void foo_asm(...);
                         // a == "void"
                         //do nothing here, so, both "extern" and "C" was skipped transparently.
                        
                    }
                }
                else
                {
                    // do nothing, just skip keyword "extern", otherwise uncomment:
                    //SkipToOneOfChars(ParserConsts::semicolon); // skip externs
                    m_Tokenizer.UngetToken();
                }
                m_Str.Clear();

  

This is a brief algorithm in my mind, I haven't much time to test it, but I think you can test it. :D
remember:
GetToken() just eat the next Token
PeekToken() just do a peek at the next Token, but NOT eat the next Token.
Title: Re: extern "C" not working with CC
Post by: daniloz on February 11, 2011, 04:21:18 pm
This is a brief algorithm in my mind, I haven't much time to test it, but I think you can test it. :D
remember:
GetToken() just eat the next Token
PeekToken() just do a peek at the next Token, but NOT eat the next Token.
Thanks for the fix and for the explanation, the only thing I changed is that I used ParserConsts::opbrace instead of "{", so I have the following code, which works 100%!! :-)
Code
else if (token == ParserConsts::kw_extern)
            {
                // check for "C", "C++"
                m_Str = m_Tokenizer.GetToken();
                if (m_Str == ParserConsts::kw_C || m_Str == ParserConsts::kw_CPP)
                {
                wxString a = m_Tokenizer.PeekToken();
                if (a == ParserConsts::opbrace)
{
m_Tokenizer.GetToken(); // "eat" {
DoParse(); // time for recursion ;)
}
else
{ // here we have something like extern "C" void foo_asm(...);
                                // a == "void"
} //do nothing here, so, both "extern" and "C" was skipped transparently.
                }
                else
                {
                    // do nothing, just skip keyword "extern", otherwise uncomment:
                    //SkipToOneOfChars(ParserConsts::semicolon); // skip externs
                    m_Tokenizer.UngetToken();
                }
                m_Str.Clear();
            }
Title: Re: extern "C" not working with CC
Post by: ollydbg on February 12, 2011, 03:34:02 am
@loaden
I think the rev 6984 has some problems, even the "{" is skipped, Doparse() will still be called. This is not necessary.