Hi All,
I have some function in assembly (on a DSP project) and I use the following syntax to declare them in C++:
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:
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 ?
Oh, sorry, I just review the code in "parserthread.cpp"
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:
m_Tokenizer.GetToken(); // "eat" {
I think we need to check the Token is a "{" or not, am I right?
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:
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
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...
It may be a bug, see the statement:
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.
// 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.
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%!! :-)
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();
}