I just create a very simple test case from the "wxWidgets-3.0.0\include\wx\dataview.h" , which failed in our CCTest.
// bit masks for the various column attributes
enum
{
// column can be resized (included in default flags)
wxCOL_RESIZABLE = 1,
// column can be clicked to toggle the sort order by its contents
wxCOL_SORTABLE = 2,
// column can be dragged to change its order (included in default)
wxCOL_REORDERABLE = 4,
// column is not shown at all
wxCOL_HIDDEN = 8,
// default flags for wxHeaderColumn ctor
wxCOL_DEFAULT_FLAGS = wxCOL_RESIZABLE | wxCOL_REORDERABLE
};
// for compatibility only, do not use
enum wxDataViewColumnFlags
{
wxDATAVIEW_COL_RESIZABLE = wxCOL_RESIZABLE,
wxDATAVIEW_COL_SORTABLE = wxCOL_SORTABLE,
wxDATAVIEW_COL_REORDERABLE = wxCOL_REORDERABLE,
wxDATAVIEW_COL_HIDDEN = wxCOL_HIDDEN
};
class AAA
{
int m_aaa;
};
AAA b;
//b.//m_aaa
Note: I believe our parser failed on the line "wxDATAVIEW_COL_HIDDEN = wxCOL_HIDDEN".
Edit: Changes to C++ code style.
I debugged a while, and I found that the bug is introduced in r9642.
The reason is that:
enum wxDataViewColumnFlags
{
wxDATAVIEW_COL_RESIZABLE = wxCOL_RESIZABLE,
wxDATAVIEW_COL_SORTABLE = wxCOL_SORTABLE,
wxDATAVIEW_COL_REORDERABLE = wxCOL_REORDERABLE,
wxDATAVIEW_COL_HIDDEN = wxCOL_HIDDEN
};
Note that wxCOL_HIDDEN is not a member token of the wxDataViewColumnFlags, so the below code goes to the else clause.
bool ParserThread::CalcEnumExpression(Token* tokenParent, long& result, wxString& peek)
{
// need to force the tokenizer skip raw expression
const TokenizerState oldState = m_Tokenizer.GetState();
// expand macros, but don't read a single parentheses
m_Tokenizer.SetState(tsRawExpression);
Expression exp;
wxString token, next;
while (IS_ALIVE)
{
token = m_Tokenizer.GetToken();
if (token.IsEmpty())
return false;
if (token == _T("\\"))
continue;
if (token == ParserConsts::comma || token == ParserConsts::clbrace)
{
m_Tokenizer.UngetToken();
peek = token;
break;
}
if (token == ParserConsts::dcolon)
{
peek = SkipToOneOfChars(ParserConsts::commaclbrace);
exp.Clear();
break;
}
if (wxIsalpha(token[0]) || token[0] == ParserConsts::underscore_chr) // handle enum or macro
{
const Token* tk = m_TokenTree->at(m_TokenTree->TokenExists(token, tokenParent->m_Index, tkEnumerator));
if (tk) // the enumerator token
{
if (!tk->m_Args.IsEmpty() && wxIsdigit(tk->m_Args[0]))
token = tk->m_Args; // add the value to exp
}
else
{
peek = SkipToOneOfChars(ParserConsts::commaclbrace);
exp.Clear();
break;
}
}
I just debugged into the function SkipToOneOfChars(ParserConsts::commaclbrace), I see that the "}" is already eat in this function. When up to the caller "void ParserThread::HandleEnum()", we will eat another token after "}", and finally the code after that will be eat, and the body of class AAA is totally skipped.
I just debugged into the function SkipToOneOfChars(ParserConsts::commaclbrace), I see that the "}" is already eat in this function. When up to the caller "void ParserThread::HandleEnum()", we will eat another token after "}", and finally the code after that will be eat, and the body of class AAA is totally skipped.
Yes, we can see from:
if (token == ParserConsts::comma || token == ParserConsts::clbrace)
{
m_Tokenizer.UngetToken();
peek = token;
break;
}
that UngetToken() is used if we already skipped comma or clbrace. We can do the same thing after SkipToOneOfChars().
This patch should fix it:
diff --git a/src/plugins/codecompletion/parser/parserthread.cpp b/src/plugins/codecompletion/parser/parserthread.cpp
index d882063..d35010c 100644
--- a/src/plugins/codecompletion/parser/parserthread.cpp
+++ b/src/plugins/codecompletion/parser/parserthread.cpp
@@ -2655,6 +2655,7 @@ bool ParserThread::CalcEnumExpression(Token* tokenParent, long& result, wxString
if (token == ParserConsts::dcolon)
{
peek = SkipToOneOfChars(ParserConsts::commaclbrace);
+ m_Tokenizer.UngetToken();
exp.Clear();
break;
}
@@ -2671,6 +2672,7 @@ bool ParserThread::CalcEnumExpression(Token* tokenParent, long& result, wxString
else
{
peek = SkipToOneOfChars(ParserConsts::commaclbrace);
+ m_Tokenizer.UngetToken();
exp.Clear();
break;
}
Edit: Applied syntax highlighting for diff.
I just debugged into the function SkipToOneOfChars(ParserConsts::commaclbrace), I see that the "}" is already eat in this function. When up to the caller "void ParserThread::HandleEnum()", we will eat another token after "}", and finally the code after that will be eat, and the body of class AAA is totally skipped.
Yes, we can see from:
if (token == ParserConsts::comma || token == ParserConsts::clbrace)
{
m_Tokenizer.UngetToken();
peek = token;
break;
}
that UngetToken() is used if we already skipped comma or clbrace. We can do the same thing after SkipToOneOfChars().
This patch should fix it:
...
Yes, it fix the bug, thanks. Also the Op's issue is fixed by this patch.
My idea is that: is it better to check some thing in this code:
if (peek == ParserConsts::comma || peek == ParserConsts::clbrace)
{
// this "if", avoids non-valid enumerators
// like a comma (if no enumerators follow)
if ( wxIsalpha(token.GetChar(0))
|| (token.GetChar(0) == ParserConsts::underscore_chr) )
{
wxString args;
if (updateValue)
args << enumValue++;
Token* lastParent = m_LastParent;
m_LastParent = newEnum;
Token* enumerator = DoAddToken(tkEnumerator, token, m_Tokenizer.GetLineNumber(), 0, 0, args);
enumerator->m_Scope = isEnumClass ? tsPrivate : tsPublic;
m_LastParent = lastParent;
}
// add check here
// if (peek == ParserConsts::clbrace)
// break?
}
I don't test it yet, but just read and modify the source code.