User forums > Announcements
Release 15.12, RC1 has arrived
ollydbg:
To simplify the issue, you can simply create a simple cpp file, which does not include any other files:
--- Code: ---# define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V)
namespace std _GLIBCXX_VISIBILITY(default)
{
class vector
{
size_t size();
}
}
--- End code ---
Then, you can type "std::"
If the std namespace is parse correctly, then you should show "std::vector", but actually it is not.
ollydbg:
--- Code: ---void ParserThread::HandleNamespace()
{
wxString ns = m_Tokenizer.GetToken();
int line = m_Tokenizer.GetLineNumber();
if (ns == ParserConsts::opbrace)
{
// parse inside anonymous namespace
Token* lastParent = m_LastParent;
TokenScope lastScope = m_LastScope;
DoParse();
m_LastParent = lastParent;
m_LastScope = lastScope;
}
else
{
// for namespace aliases to be parsed, we need to tell the tokenizer
// not to skip the usually unwanted tokens. One of those tokens is the
// "assignment" (=).
// we just have to remember to revert this setting below, or else problems will follow
m_Tokenizer.SetState(tsNormal);
wxString next = m_Tokenizer.PeekToken(); // named namespace
if (next==ParserConsts::opbrace)
{
m_Tokenizer.SetState(tsNormal);
// use the existing copy (if any)
Token* newToken = TokenExists(ns, m_LastParent, tkNamespace);
if (!newToken)
newToken = DoAddToken(tkNamespace, ns, line);
if (!newToken)
{
TRACE(_T("HandleNamespace() : Unable to create/add new token: ") + ns);
return;
}
m_Tokenizer.GetToken(); // eat {
int lineStart = m_Tokenizer.GetLineNumber();
Token* lastParent = m_LastParent; // save status, will restore after DoParse()
TokenScope lastScope = m_LastScope;
m_LastParent = newToken;
// default scope is: public for namespaces (actually no, but emulate it)
m_LastScope = tsPublic;
DoParse();
m_LastParent = lastParent;
m_LastScope = lastScope;
// update implementation file and lines of namespace.
// this doesn't make much sense because namespaces are all over the place,
// but do it anyway so that buffer-based parsing returns the correct values.
newToken->m_ImplFileIdx = m_FileIdx;
newToken->m_ImplLine = line;
newToken->m_ImplLineStart = lineStart;
newToken->m_ImplLineEnd = m_Tokenizer.GetLineNumber();
}
else if (next==ParserConsts::equals)
{
// namespace alias; example from cxxabi.h:
//
// namespace __cxxabiv1
// {
// ...
// }
// namespace abi = __cxxabiv1; <-- we 're in this case now
m_Tokenizer.GetToken(); // eat '='
m_Tokenizer.SetState(tsNormal);
Token* lastParent = m_LastParent;
Token* aliasToken = NULL;
while (IS_ALIVE)
{
wxString aliasStr = m_Tokenizer.GetToken();
// use the existing copy (if any)
aliasToken = TokenExists(aliasStr, m_LastParent, tkNamespace);
if (!aliasToken)
aliasToken = DoAddToken(tkNamespace, aliasStr, line);
if (!aliasToken)
return;
if (m_Tokenizer.PeekToken() == ParserConsts::dcolon)
{
m_Tokenizer.GetToken();
m_LastParent = aliasToken;
}
else
break;
}
aliasToken->m_Aliases.Add(ns);
m_LastParent = lastParent;
}
else
{
m_Tokenizer.SetState(tsNormal);
// probably some kind of error in code ?
SkipToOneOfChars(ParserConsts::semicolonopbrace);
}
}
}
--- End code ---
For the above code, I see that it finally run the SkipToOneOfChars(ParserConsts::semicolonopbrace);
So that the "{" is skipped, thus the "vector" token is put in the global namespace.
ollydbg:
In the above example, the three token will be skipped from the function SkipToOneOfChars(ParserConsts::semicolonopbrace);
--- Code: ---1, _GLIBCXX_PSEUDO_VISIBILITY
2, (default)
3, {
--- End code ---
I think the fix should be:
If we skip from the "{", we should handle it like the code before:
--- Code: --- wxString next = m_Tokenizer.PeekToken(); // named namespace
if (next==ParserConsts::opbrace)
{
m_Tokenizer.SetState(tsNormal);
// use the existing copy (if any)
Token* newToken = TokenExists(ns, m_LastParent, tkNamespace);
if (!newToken)
newToken = DoAddToken(tkNamespace, ns, line);
if (!newToken)
{
TRACE(_T("HandleNamespace() : Unable to create/add new token: ") + ns);
return;
}
m_Tokenizer.GetToken(); // eat {
int lineStart = m_Tokenizer.GetLineNumber();
Token* lastParent = m_LastParent; // save status, will restore after DoParse()
TokenScope lastScope = m_LastScope;
m_LastParent = newToken;
// default scope is: public for namespaces (actually no, but emulate it)
m_LastScope = tsPublic;
DoParse();
...
...
--- End code ---
The function DoParse() will carefully parse the body inside the "{ .... }", and put the "class vector" as a child of std namespace.
ollydbg:
This is the patch to fix such issue:
--- Code: --- src/plugins/codecompletion/parser/parserthread.cpp | 166 ++++++++++++---------
1 file changed, 97 insertions(+), 69 deletions(-)
diff --git a/src/plugins/codecompletion/parser/parserthread.cpp b/src/plugins/codecompletion/parser/parserthread.cpp
index a22cb61..bd9a31f 100644
--- a/src/plugins/codecompletion/parser/parserthread.cpp
+++ b/src/plugins/codecompletion/parser/parserthread.cpp
@@ -1762,95 +1762,123 @@ void ParserThread::HandleNamespace()
}
else
{
- // for namespace aliases to be parsed, we need to tell the tokenizer
- // not to skip the usually unwanted tokens. One of those tokens is the
- // "assignment" (=).
- // we just have to remember to revert this setting below, or else problems will follow
- m_Tokenizer.SetState(tsNormal);
- wxString next = m_Tokenizer.PeekToken(); // named namespace
- if (next==ParserConsts::opbrace)
+ while (true)
{
+ // for namespace aliases to be parsed, we need to tell the tokenizer
+ // not to skip the usually unwanted tokens. One of those tokens is the
+ // "assignment" (=).
+ // we just have to remember to revert this setting below, or else problems will follow
m_Tokenizer.SetState(tsNormal);
- // use the existing copy (if any)
- Token* newToken = TokenExists(ns, m_LastParent, tkNamespace);
- if (!newToken)
- newToken = DoAddToken(tkNamespace, ns, line);
- if (!newToken)
+ wxString next = m_Tokenizer.PeekToken(); // named namespace
+ if (next==ParserConsts::opbrace)
{
- TRACE(_T("HandleNamespace() : Unable to create/add new token: ") + ns);
- return;
- }
+ m_Tokenizer.SetState(tsNormal);
- m_Tokenizer.GetToken(); // eat {
- int lineStart = m_Tokenizer.GetLineNumber();
+ // use the existing copy (if any)
+ Token* newToken = TokenExists(ns, m_LastParent, tkNamespace);
+ if (!newToken)
+ newToken = DoAddToken(tkNamespace, ns, line);
+ if (!newToken)
+ {
+ TRACE(_T("HandleNamespace() : Unable to create/add new token: ") + ns);
+ return;
+ }
- Token* lastParent = m_LastParent; // save status, will restore after DoParse()
- TokenScope lastScope = m_LastScope;
+ m_Tokenizer.GetToken(); // eat {
+ int lineStart = m_Tokenizer.GetLineNumber();
- m_LastParent = newToken;
- // default scope is: public for namespaces (actually no, but emulate it)
- m_LastScope = tsPublic;
+ Token* lastParent = m_LastParent; // save status, will restore after DoParse()
+ TokenScope lastScope = m_LastScope;
- DoParse();
+ m_LastParent = newToken;
+ // default scope is: public for namespaces (actually no, but emulate it)
+ m_LastScope = tsPublic;
- m_LastParent = lastParent;
- m_LastScope = lastScope;
-
- // update implementation file and lines of namespace.
- // this doesn't make much sense because namespaces are all over the place,
- // but do it anyway so that buffer-based parsing returns the correct values.
- newToken->m_ImplFileIdx = m_FileIdx;
- newToken->m_ImplLine = line;
- newToken->m_ImplLineStart = lineStart;
- newToken->m_ImplLineEnd = m_Tokenizer.GetLineNumber();
- }
- else if (next==ParserConsts::equals)
- {
- // namespace alias; example from cxxabi.h:
- //
- // namespace __cxxabiv1
- // {
- // ...
- // }
- // namespace abi = __cxxabiv1; <-- we 're in this case now
-
- m_Tokenizer.GetToken(); // eat '='
- m_Tokenizer.SetState(tsNormal);
+ DoParse();
- Token* lastParent = m_LastParent;
- Token* aliasToken = NULL;
+ m_LastParent = lastParent;
+ m_LastScope = lastScope;
- while (IS_ALIVE)
+ // update implementation file and lines of namespace.
+ // this doesn't make much sense because namespaces are all over the place,
+ // but do it anyway so that buffer-based parsing returns the correct values.
+ newToken->m_ImplFileIdx = m_FileIdx;
+ newToken->m_ImplLine = line;
+ newToken->m_ImplLineStart = lineStart;
+ newToken->m_ImplLineEnd = m_Tokenizer.GetLineNumber();
+
+ // the namespace body is correctly parsed
+ break;
+ }
+ else if (next==ParserConsts::equals)
{
- wxString aliasStr = m_Tokenizer.GetToken();
+ // namespace alias; example from cxxabi.h:
+ //
+ // namespace __cxxabiv1
+ // {
+ // ...
+ // }
+ // namespace abi = __cxxabiv1; <-- we 're in this case now
- // use the existing copy (if any)
- aliasToken = TokenExists(aliasStr, m_LastParent, tkNamespace);
- if (!aliasToken)
- aliasToken = DoAddToken(tkNamespace, aliasStr, line);
- if (!aliasToken)
- return;
+ m_Tokenizer.GetToken(); // eat '='
+ m_Tokenizer.SetState(tsNormal);
- if (m_Tokenizer.PeekToken() == ParserConsts::dcolon)
+ Token* lastParent = m_LastParent;
+ Token* aliasToken = NULL;
+
+ while (IS_ALIVE)
{
- m_Tokenizer.GetToken();
- m_LastParent = aliasToken;
+ wxString aliasStr = m_Tokenizer.GetToken();
+
+ // use the existing copy (if any)
+ aliasToken = TokenExists(aliasStr, m_LastParent, tkNamespace);
+ if (!aliasToken)
+ aliasToken = DoAddToken(tkNamespace, aliasStr, line);
+ if (!aliasToken)
+ return;
+
+ if (m_Tokenizer.PeekToken() == ParserConsts::dcolon)
+ {
+ m_Tokenizer.GetToken();
+ m_LastParent = aliasToken;
+ }
+ else
+ break;
}
+
+ aliasToken->m_Aliases.Add(ns);
+ m_LastParent = lastParent;
+
+ // the namespace alias statement is correctly parsed
+ break;
+ }
+ else
+ {
+ m_Tokenizer.SetState(tsNormal);
+ // probably some kind of error in code ?
+ SkipToOneOfChars(ParserConsts::semicolonopbrace);
+
+ // in case of the code:
+ //
+ // # define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V)
+ // namespace std _GLIBCXX_VISIBILITY(default)
+ // {
+ // class vector
+ // {
+ // size_t size();
+ // }
+ // }
+ // we still want to parse the body of the namespace, but skip the tokens before "{"
+ m_Tokenizer.UngetToken();
+ wxString peek = m_Tokenizer.PeekToken();
+ if(peek == ParserConsts::opbrace)
+ continue;
else
break;
}
-
- aliasToken->m_Aliases.Add(ns);
- m_LastParent = lastParent;
- }
- else
- {
- m_Tokenizer.SetState(tsNormal);
- // probably some kind of error in code ?
- SkipToOneOfChars(ParserConsts::semicolonopbrace);
- }
+ } // while(true)
}
}
--- End code ---
Please test and give feedback. The method I use is: I just check which token is skipped by the SkipToOneOfChars(), if it is the "{", then I need to still parse it as the beginning of the namespace body.
The issue I see that, when I hit the dot, I see the suggestion window pop up, and disappeared quickly, so no suggestion after the dot. I'm not sure the reason. But if I continue enter the member function, like "push_", I get the correct result, see the image shot below:
The patch is in GIT style, so you need the patch utility to apply it in your local copy.
MortenMacFly:
--- Quote from: ollydbg on December 10, 2015, 02:27:52 am ---This is the patch to fix such issue:
--- End quote ---
That looks very good - its working for me again now.
Great work! I'll some some more testing on larger projects but so far I see no negative side-effects. If you commit, please also add the source snippet to the test cases.
BTW: The patch applied as-it-is just fine.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version