Author Topic: Code completion does not solve STDMETHOD macro for COM interfaces  (Read 22785 times)

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Code completion does not solve STDMETHOD macro for COM interfaces
« on: September 20, 2014, 08:18:40 am »
As the title said I could not get any correct code completion hints for all the COM interfaces and theirs' methods.

I also noticed that there's a 'Replacement Tokens' option in the 'C/C++ parser(adv) panel of C::B->Settings->Editor->Code completions settings,
so I tried to add a 'DECLARE_INTERFACE_ -> +struct INTERFACE' replacement and the code completions is going to recognize the COM interfaces now,
but I could not find suitable patterns for the STDMETHOD macro, so I'm still not able to get code completion solving the methods for COM interfaces.

Many thanks if anyone could give me some advice. ;D

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #1 on: September 21, 2014, 05:17:40 am »
I would recommend you can create a simple/minimal test cpp file, which contains the code patters of the unrecognized code snippet. So, we can test and try to fix it.
(the test cpp file should not include any other COM related files, because I don't have any COM related header files in my system.)
Thank you for the report.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #2 on: September 21, 2014, 12:08:53 pm »
Thank you for the recommend.
I copied & pasted a minimum sample from a MinGW header 'unknwn.h' to reproduce this issue.

Code
#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)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #3 on: September 21, 2014, 03:55:57 pm »
OK, thanks for the sample code. I little complex for me since it use a lot of macros.
What is the expect suggestion list if you press the "unknwown->"?
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #4 on: September 21, 2014, 04:41:28 pm »
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:
Code
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:
Code
[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.
« Last Edit: September 21, 2014, 04:56:47 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #5 on: September 21, 2014, 07:22:52 pm »
Thank you so much for the debugging so that I can try to find out some ways to have it a hot fix.
Code
[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:
Code
#define STDMETHOD(m) virtual HRESULT STDMETHODCALLTYPE m
#define STDMETHOD_(t,m) virtual t STDMETHODCALLTYPE m
with this code:
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?

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #6 on: September 21, 2014, 08:22:37 pm »
Here have a code snippet:
Code
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:
Code
[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 :(
Yes, we are using m_FullType.Find() to see if m_Name is a sub-string of m_FullType, so it doesn't see any difference between STDMETHOD and STDMETHODCALLTYPE.  ::)

A quick way to fix it is to just disable this test. We have macro replacement limited to s_MaxRepeatReplaceCount, so we won't get infinite replacement loop anyway. So if m_FullType contains m_Name we assume the user knows what he is doing and we just try to continue expansion.
« Last Edit: September 21, 2014, 08:28:35 pm by Huki »

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #7 on: September 21, 2014, 08:45:11 pm »
Thank you so much for the debugging so that I can try to find out some ways to have it a hot fix.
Code
[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:
Code
#define STDMETHOD(m) virtual HRESULT STDMETHODCALLTYPE m
#define STDMETHOD_(t,m) virtual t STDMETHODCALLTYPE m
with this code:
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:




Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #8 on: September 22, 2014, 04:14:42 am »
...
but it doesn't seem to be any help to code completion expending STDMETHOD or STDMETHOD_ macro, any ideas?
You need a patch by Huki, see: Re: Is it possible for the parser to support newlib prototypes?

...
After replacing STDMETHODCALLTYPE with __stdcall I get the correct results with code completion. See below:




I can get expected function shown in the suggestion list. But in my suggestion list, I see a lot of global namespace tokens, not sure why those global tokens were shown, need time to debug.
EDIT: issue fixed since I was disable the smart sense option of CC. I get the same suggestion list as Huki now.  ;)
« Last Edit: September 22, 2014, 08:36:40 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #9 on: September 22, 2014, 07:02:29 am »
Thank you so much for the debugging so that I can try to find out some ways to have it a hot fix.
Code
[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:
Code
#define STDMETHOD(m) virtual HRESULT STDMETHODCALLTYPE m
#define STDMETHOD_(t,m) virtual t STDMETHODCALLTYPE m
with this code:
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:





Thanks for the help Huki, but CC is still not going to parse it unless removing the __stdcall from macro definition:
Code
#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?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #10 on: September 22, 2014, 08:43:25 am »
...
Thanks for the help Huki, but CC is still not going to parse it unless removing the __stdcall from macro definition:
Code
#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:
Code
 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)
« Last Edit: September 22, 2014, 08:51:01 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #11 on: September 22, 2014, 09:31:13 am »
I found that  The 16 September 2014 build (9916) has applied Huki's patch,
I tried it and modified the header with __stdcall, it did fix the problem, but the nightly builds(9916 & 9884) recently released both have an issue: eating up a core's CPU time,
then C::B become extremely slow under Windows 8.1 x64 with default C::B settings, I have to remove all the plugins(except some core plugins and of course the code completion) to make C::B run gracefully.
Anyway, thank you very much for the help :P

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #12 on: September 22, 2014, 10:15:14 am »
I found that  The 16 September 2014 build (9916) has applied Huki's patch,
I tried it and modified the header with __stdcall, it did fix the problem,
Grad to hear, I was mentioned an testing patch which is not in trunk, but it looks like we don't need such patch to solve your issue;)

Quote
but the nightly builds(9916 & 9884) recently released both have an issue: eating up a core's CPU time,
then C::B become extremely slow under Windows 8.1 x64 with default C::B settings, I have to remove all the plugins(except some core plugins and of course the code completion) to make C::B run gracefully.
Anyway, thank you very much for the help :P
This is really a big problem, If you can supply a test case, I'm going to hunt this issue. (mostly, I think it is CodeCompletion which cause the issue)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #13 on: September 22, 2014, 04:50:54 pm »
I think this issue could be confirmed, I also test it under windows 2003 x64 in a virtual machine, same behavior as my win8.1 x64 PC.
I also try about removing codecompletion.dll from the plugins folder and restart C::B, but that does not help anything...So I think we should spend some time to find which plugins produce this issue.

[attachment deleted by admin]

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #14 on: September 22, 2014, 06:22:07 pm »
I think this issue could be confirmed, I also test it under windows 2003 x64 in a virtual machine, same behavior as my win8.1 x64 PC.
I also try about removing codecompletion.dll from the plugins folder and restart C::B, but that does not help anything...So I think we should spend some time to find which plugins produce this issue.
Does it happen without any plugins ?
I ask because we have changes in (wx-)scintilla that use timers and this is at least a change, that might be related to time consuming behaviour.

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #15 on: September 22, 2014, 08:01:40 pm »
No, it doesn't happen with a number of core plugins and auto completion plugin.
So I think that should be issued by a plugin or conflicts between plugins.

Edit: After removing FileManager.dll from plugins folder, I could run C::B as usual but when I close C::B, it still leave a dead process and eat one core CPU time in the background.
« Last Edit: September 22, 2014, 08:06:54 pm by GPBeta »

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #16 on: September 22, 2014, 09:54:13 pm »
Could you try what happens if you remove the "FileManager.dll" from the "share\plugins\CodeBlocks"-folder, instead of just disabling the FileManager-plugin ?

Offline GPBeta

  • Multiple posting newcomer
  • *
  • Posts: 13
  • Just a Baka
    • StudioGPBeta
Re: Code completion does not solve STDMETHOD macro for COM interfaces
« Reply #17 on: September 23, 2014, 05:01:05 am »
Yes, this is what I have done. Because there's no change for me to see the main frame of C::B , I could not open the plug-in manager under such circumstance so I have to remove it from the "share\CodeBlocks\plugins" folder manually and directly.