Author Topic: extern "C" not working with CC  (Read 18352 times)

Offline daniloz

  • Regular
  • ***
  • Posts: 268
extern "C" not working with CC
« 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 ?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6035
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: extern "C" not working with CC
« Reply #1 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.
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.

Offline daniloz

  • Regular
  • ***
  • Posts: 268
Re: extern "C" not working with CC
« Reply #2 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... ;-)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6035
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: extern "C" not working with CC
« Reply #3 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?
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.

Offline daniloz

  • Regular
  • ***
  • Posts: 268
Re: extern "C" not working with CC
« Reply #4 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...

Offline Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: extern "C" not working with CC
« Reply #5 on: February 11, 2011, 03:56:06 pm »
It should been fixed in next nightly build.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6035
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: extern "C" not working with CC
« Reply #6 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.
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.

Offline daniloz

  • Regular
  • ***
  • Posts: 268
Re: extern "C" not working with CC
« Reply #7 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();
            }

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6035
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: extern "C" not working with CC
« Reply #8 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.
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.