Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => Topic started by: EnterTheNameHere on July 31, 2013, 02:23:37 pm

Title: Code-Completion compiler built-in defines and c++ version
Post by: EnterTheNameHere on July 31, 2013, 02:23:37 pm
The code completion doesn't take into account the c++ version when asking for builtin defines from compiler.


(SVN revision at the time of writting: 9239)
In the file "plugins\codecompletion\nativeparser.cpp",
function NativeParser::AddCompilerPredefinedMacrosGCC,
on the line 2170 is the command to get the builtin defines
Code: c++
#ifdef __WXMSW__
        const wxString args(_T(" -E -dM -x c++ nul"));
#else
        const wxString args(_T(" -E -dM -x c++ /dev/null"));
#endif

This command doesn't take into account if user wants to compile project with -std=c++11 (-std=c++0x).
It means the __cplusplus define is always 199711L, instead of 201103L. Code completion then ignores std::shared_ptr, std::enable_if, [map::]emplace and other tokens which are "hidden" under #if __cplusplus >= 201103L.

I tried hacking the code to
Code: c++
#ifdef __WXMSW__
        const wxString args(_T(" -E -dM -std=c++11 -x c++ nul"));
#else
        const wxString args(_T(" -E -dM -std=c++11 -x c++ /dev/null"));
#endif

and then the __cplusplus define is 201103L (checked under Symbols(View: Everything)->#Preprocessor symbols) and code completion can successfuly parse std::shared_ptr, std::enable_if, [map::]emplace and emplace_hint and other tokens.

Unfortunately I don't know Code::Blocks source code well enough to make an adequate patch depending of project compiler options...
Title: Re: Code-Completion compiler built-in defines and c++ version
Post by: EnterTheNameHere on August 24, 2013, 10:17:22 pm
So the problem for me was the NativeParser::AddCompilerPredefinedMacrosGCC() function only looks if "-std=c++0x" or "-std=gnu++0x" is set in project/target compiler options, and if it is, it will add __GXX_EXPERIMENTAL_CXX0X__ to defines.

I am using -std=c++11 and GCC 4.8.1-2, which is already using #if __cplusplus > 199711L, not __GXX_EXPERIMENTAL_CXX0X__, so parser couldn't parse c++11 features like std::shared_ptr, even with -std=c++0x.

I have rewritten the function to look for "-std=", so now You can specify any standard You want (eg. -std=c++11, -std=gnu++11, -std=c89, -std=gnu11 or even -std=iso9899:199409), and this standard will be used in the query to compiler. First the global compiler options are searched, if standard is set there. If not, as second the project compiler options are searched. Targets are searched as third in row, getting the first standard that is encountered. If no standard is set, no standard will be sent to compiler, so compiler will return defines for the default standard (__cplusplus 199711L).

Patch can be found here:
http://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=3493&group_id=5358
Title: Re: Code-Completion compiler built-in defines and c++ version
Post by: oBFusCATed on August 25, 2013, 08:51:48 pm
First the global compiler options are searched, if standard is set there. If not, as second the project compiler options are searched. Targets are searched as third in row, getting the first standard that is encountered. If no standard is set, no standard will be sent to compiler, so compiler will return defines for the default standard (__cplusplus 199711L).
From this description it sounds like you're doing it wrong. You should search first the target, then the project and last global settings. For the target there is an option telling if it should override the project settings, append to them and so on.

@devs: Do you know if there is an API for querying if compiler or linker option is set?
Title: Re: Code-Completion compiler built-in defines and c++ version
Post by: EnterTheNameHere on August 26, 2013, 01:51:10 pm
Good point, thank You, I'll update it.

BTW the compiler takes into account the latest standard passed on command line, so "g++.exe -std=c++1y -g -std=c++11 -wAll -std=c++98" will yield defines for c++98. From my test the global compiler options are appended to the end - so it overrides any other standard set - and that's why I search globals as first. I think it's correct behavior for parser then...

So should the order be:
1. Compiler global options
2. Target options - I check if targets appends to/discards project options
3. Project options
4. Target options - I check if targets prepends to project options

ie.
g++.exe [Target prepend options] [Project options] [Target append options] [Target only options] [Compiler global options]

However neither of this take into account the current behavior of parser. If I understand it correctly, the defines are now loaded _only once_ after Code::Blocks is(are) run, on the loading of first project/workspace or individual file. Even if You close-load new project or workspace, or file, defines are never queried again.

So should the parser take into account current project (ie. the project to which the current file belongs to) and target and requery defines too?