User forums > Announcements

Release 15.12, RC1 has arrived

<< < (3/17) > >>

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