Thank you for the recommend.
I copied & pasted a minimum sample from a MinGW header 'unknwn.h' to reproduce this issue.
#define _COM_interface struct
#define interface _COM_interface
#define DECLARE_INTERFACE(i) _COM_interface i
#define DECLARE_INTERFACE_(i,b) _COM_interface i : public b
#define PURE =0
#define STDMETHODCALLTYPE __stdcall
#define STDMETHOD(m) virtual HRESULT STDMETHODCALLTYPE m
#define STDMETHOD_(t,m) virtual t STDMETHODCALLTYPE m
#define REFIID const IID&
#define THIS_
#define THIS void
typedef struct GUID IID;
typedef unsigned long ULONG;
typedef long HRESULT;
typedef bool BOOL;
typedef void *PVOID;
DECLARE_INTERFACE(IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
};
typedef IUnknown *LPUNKNOWN;
DECLARE_INTERFACE_(IClassFactory,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(CreateInstance)(THIS_ LPUNKNOWN,REFIID,PVOID*) PURE;
STDMETHOD(LockServer)(THIS_ BOOL) PURE;
};
int main()
{
IUnknown* unknwown;
IClassFactory* factory;
return 0;
}
You can see the code completion does not resolve symbols correctly as my attachment image shown, both hints for IUnknown & IClassFactory interfaces are wrong.
(occurring in Code::Blocks 13.12 stable and recent nightly builds)
I just debugged the code, and I see we get a failure when expanding the macro usage of:
STDMETHOD(QueryInterface)
Here have a code snippet:
bool Tokenizer::GetMacroExpandedText(const Token* tk, wxString& expandedText)
{
// e.g. "#define AAA AAA" and usage "AAA(x)"
if (!tk || tk->m_Name == tk->m_FullType)
return false;
// sanity check if we have such macro definition that #define AAA(x,y) x+y+AAA
// if a macro name exists in its definition, it will cause a infinite expansion loop
if (tk->m_FullType.Find(tk->m_Name) != wxNOT_FOUND)
return false;
Here, the macro definition token tk is:
[debug]> p *tk
[debug]$3 = {m_FullType = L"virtual HRESULT STDMETHODCALLTYPE m", m_BaseType = L"m", m_Name = L"STDMETHOD", m_Args = L"(m)",
Now, I see that m_FullType contains the m_Name, so we just stop expansion, and return false to avoid infinite recursive call :(
It looks like this case, we should still expand, also we should improve how macro expansion works in our CC's parser.
EDIT:
The reason of this issue is that currently, expansion of macro usage just do some text replacement, but we never consider the text as a token serials. So, the improvement should be use the Tokenizer::DoGetToken() function with tsReadRawExpression bit set, so that we get a raw token sequence(we can store them in a wxArrayString), and later, we need to compare each element. Thus, we need to remove all the KMP related functions, since they are generally search for the plain text, not the token sequence.
Thank you so much for the debugging so that I can try to find out some ways to have it a hot fix.
[debug]$3 = {m_FullType = L"virtual HRESULT STDMETHODCALLTYPE m", m_BaseType = L"m", m_Name = L"STDMETHOD", m_Args = L"(m)"
According to the debug info, m_FullType contains the m_Name, then parsing process interrupt.
So I replaced the macro in the sample:
#define STDMETHOD(m) virtual HRESULT STDMETHODCALLTYPE m
#define STDMETHOD_(t,m) virtual t STDMETHODCALLTYPE m
with this code:
#define STDMETHOD(m) virtual HRESULT __stdcall m
#define STDMETHOD_(t,m) virtual t __stdcall m
Now the m_Name("STDMETHOD") does not match any sub strings in m_FullType("virtual HRESULT __stdcall m"),
but it doesn't seem to be any help to code completion expending STDMETHOD or STDMETHOD_ macro, any ideas?
Thank you so much for the debugging so that I can try to find out some ways to have it a hot fix.
[debug]$3 = {m_FullType = L"virtual HRESULT STDMETHODCALLTYPE m", m_BaseType = L"m", m_Name = L"STDMETHOD", m_Args = L"(m)"
According to the debug info, m_FullType contains the m_Name, then parsing process interrupt.
So I replaced the macro in the sample:
#define STDMETHOD(m) virtual HRESULT STDMETHODCALLTYPE m
#define STDMETHOD_(t,m) virtual t STDMETHODCALLTYPE m
with this code:
#define STDMETHOD(m) virtual HRESULT __stdcall m
#define STDMETHOD_(t,m) virtual t __stdcall m
Now the m_Name("STDMETHOD") does not match any sub strings in m_FullType("virtual HRESULT __stdcall m"),
but it doesn't seem to be any help to code completion expending STDMETHOD or STDMETHOD_ macro, any ideas?
After replacing STDMETHODCALLTYPE with __stdcall I get the correct results with code completion. See below:
(http://i.imgur.com/YtV4BHf.png)
(http://i.imgur.com/o2z8YgM.png)
Thanks for the help Huki, but CC is still not going to parse it unless removing the __stdcall from macro definition:
#define STDMETHOD(m) virtual HRESULT __stdcall m
#define STDMETHOD_(t,m) virtual t __stdcall m
Maybe I should try about the patch ollydbg referred and compile it myself?
...
Thanks for the help Huki, but CC is still not going to parse it unless removing the __stdcall from macro definition:
#define STDMETHOD(m) virtual HRESULT __stdcall m
#define STDMETHOD_(t,m) virtual t __stdcall m
Maybe I should try about the patch ollydbg referred and compile it myself?
To totally fix your issue, we have two steps:
1, fix macro expanding issue, to workaround it, you need Use __stdcall in the macro definition.
Or, just apply this patch:
src/plugins/codecompletion/parser/tokenizer.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/plugins/codecompletion/parser/tokenizer.cpp b/src/plugins/codecompletion/parser/tokenizer.cpp
index 8a13abd..4273d73 100644
--- a/src/plugins/codecompletion/parser/tokenizer.cpp
+++ b/src/plugins/codecompletion/parser/tokenizer.cpp
@@ -1931,8 +1931,10 @@ bool Tokenizer::GetMacroExpandedText(const Token* tk, wxString& expandedText)
// sanity check if we have such macro definition that #define AAA(x,y) x+y+AAA
// if a macro name exists in its definition, it will cause a infinite expansion loop
- if (tk->m_FullType.Find(tk->m_Name) != wxNOT_FOUND)
- return false;
+ // Note: disable this sanity check to work around the issue here:
+ // http://forums.codeblocks.org/index.php/topic,19661.msg134291.html#msg134291
+ //if (tk->m_FullType.Find(tk->m_Name) != wxNOT_FOUND)
+ // return false;
// if it's a variable like macro definition simply return the replacement text
if (tk->m_Args.IsEmpty())
2, apply Huki's patch I mentioned, and rebuild C::B(especially CodeCompletion plugin)