Qt Creator : Intellisense for C, force a given context - qt-creator

So I have Qt Creator 7.0.2. The editor parses and colors and does lots of things with a given file, using the environment and the other files included.
However for header files, it does not take into account that this file is included in some compilation unit which provides some preexisting context (macros or types declared, other files already included, etc.) . Of course, one of the reasons for that is that there are multiple possibilities, but I do not know if Qt Creator offers a way to choose a context for parsing that would match one of those possibilities. Let me give an example with macros.
The file I am viewing in the editor : header.h
#ifdef A
/* Declarations in case of A */
#endif
#ifdef B
/* Definitions in case of B */
#endif
When viewing header.h in the editor, both paragraphs (in case of A, in case of B) are grayed out because in the context of header.h alone Qt Creator / Intellisense does not see a definition of A or B - and fair enough !
A compilation unit that includes this file : compilation_unit_A.c
#define A
#include "header.h"
/* Code using the definitions from the header file in case of A */
Another compilation unit that includes this file : compilation_unit_B.c
#define B
#include "header.h"
/* Code using the definitions from the header file in case of B */
I would like Qt Creator to offer me two options for parsing : in the context of compilation_unit_A.c or in the context of compilation_unit_B.c.
Then one or the other paragraph would not be grayed out and instead parsed like normal code, because one or the other of A and B would be defined.
In my case, definitions for A and B are themselves found in other header files included in each compilation unit, but if Qt Creator / Intellisense starts looking into the preexisting code in compilation_unit_A/B.c then it would also naturally open other header files to construct a context - like it already does.
EDIT : alternatively, I have one header file that, if "pretend-included" as part of the context, would cover almost everything. Can I ask Qt Creator to include all the contents of a given header file in its parsing for the editor ?

Related

ESP32 compiler giving "multiple definition of" errors

Got a new issue I've not come across before that's appeared when using the Espressif ESP32 ESP-IDF standard setup under VSCode. It uses the GNU compiler.
I'm getting "multiple definition of" errors on variables that share the same name, but which should be local.
So I use a .c and .h pair of files approach.
In my .c files I do this at the top
#define IO_EXPANDER_C //<<<This is a unique define for this file pair
#include "io-pca9539.h"
In my .h files I do this:
#ifdef IO_EXPANDER_C
//----- INTERNAL ONLY MEMORY DEFINITIONS -----
uint8_t *NextReadDataPointer;
//----- INTERNAL & EXTERNAL MEMORY DEFINITIONS -----
//(Also defined below as extern)
int SomeVariableIWantAvailableGlobally;
#else
//----- EXTERNAL MEMORY DEFINITIONS -----
extern int SomeVariableIWantAvailableGlobally;
#endif
It's a great simple system, any other .c file that includes the .h file (without the #define above its include statemnt), gets all of its extern variables, none of its local variables.
But, compiling in VSCode with my ESP-IDF based project, I'm getting "multiple definition of" errors relating to "NextReadDataPointer"
I use the same variable name NextReadDataPointer in another file pair in just the same way, but it's never declared anywhere as extern and each file pair uses a separate #define (IO_EXPANDER_C and LED_C). I do this all the time normally and I can't see any obvious mistakes.
I've never seen a C compiler do this before, it's as if it's mixing up the local definitions somehow. A #define should only have scope in the file it is declared in and in any includes within that file.
Even odder, the error is not generated if the project is built but a function is called from just one of the file pairs that share the same local variable name. It's only generated when functions are called from both file pairs from my main application.
Can anyone shed light on whether the GNU C compiler does something funky for a standard ESP-IDF project as it's got me baffled?
uint8_t *NextReadDataPointer; creates a variable which is visible across all translation units, i.e. it's the opposite of "private". If you include this header in multiple c files and the linker tries to link those together; it'll see a conflict. The keyword you're looking for is static, for example static uint8_t *NextReadDataPointer; creates a variable that is not visible across translation units. The reason you don't see the problem if calling a function from only one of those two files is because in this case the linker doesn't bother looking into the other one.
Personally I'd avoid such clever preprocessor hacks because it's quite difficult to see how files include one another and debug the resulting problems. I'd suggest sticking to the standard way of declaring shared things in header files and keeping the private stuff inside the c file (prepended by static).

Using DEBUG_NEW correctly

Can someone please clarify if I must add this code to the top of all my CPP files, or will it be sufficient if only one CPP file defines it?
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
You need to place this macro at the top of every translation unit1 for which you wish to track memory allocations. Macros are in effect from the point where they are defined to the end of the currently compiled translation unit (unless they are undefined prior to the end).
Also note that there's a __FILE__ macro involved, which already is a strong hint that the (non-compliant) replacement of new is per-file.
1 Translation units are the input to the compiler for which it generates object code. You can roughly think of a translation unit as a preprocessed source file (commonly with a file extension of .cpp, .cc, or .cxx).

Objective-C++ compilation errors due to Xcode not respecting file type

I'm following a tutorial in a book (iPhone 3D Programming), which uses:
Objective-C header and source files (file extensions .h, .m - respectively),
Objective-C++ header and source files (file extensions .h, .mm - respectively)
C++ header and source files (file extensions .hpp, .mpp - respectively)
A sample Xcode project is included which compiles successfully.
Before I found the sample project, I had manually typed out the code from the book but I was getting the following compilation errors for the files detailed below:
Unknown type name 'virtual'
Expected member name or ';' after declaration specifiers
IRenderingEngine.hpp (Xcode File Inspector - File Type = "Default - C++ Header")
...
struct IRenderingEngine {
virtual void Initialize(int width, int height) = 0; //2 errors as marked above
virtual void Render() const = 0; //2 errors as marked above
virtual void UpdateAnimation(float timeStep) = 0; //2 errors as marked above
virtual void OnRotate(DeviceOrientation newOrientation) = 0; //2 errors as marked above
virtual ~IRenderingEngine() {} //2 errors as marked above
};
...
Must use 'struct' tag to refer to type 'IRenderingEngine'
GLView.h (Xcode File Inspector - File Type = "Default - C Header")
#import "IRenderingEngine.hpp"
#import <QuartzCore/QuartzCore.h>
#interface GLView : UIView {
#private
EAGLContext* m_context;
IRenderingEngine* m_renderingEngine; //1 error marked above
float m_timestamp;
}
- (void) drawView:(CADisplayLink*)displayLink;
- (void) didRotate:(NSNotification*)notification;
#end
The file types for all the other files also defaulted to their expected file types in the Xcode File Inspector and as such should have worked correctly with the Build Setting - Apple LLVM compiler 4.2 - Language - "Compile Sources As = According to File Type" - which is identical to the Build Setting in the sample project that compiles successfully.
For some odd reason changing the Build Setting to "Compile Sources As = Objective-C++" in my manually created project removed the compilation errors and the application ran as expected.
Can anyone offer a reason as to why this setting is not consistent between seemingly identical (source-code-wise) projects?
Header files are not compiled. Header files are used by the preprocessor — anywhere you have a #include or a #import the actual text of the original is treated as though you'd copied and pasted it into the original.
Hence it doesn't matter if your file is called .hpp, .h or anything else. If a .m file imports a .h file that includes a .hpp file then the .hpp code will be compiled as part of the .m file, i.e. as Objective-C.
I am therefore going to guess that you've got GLView.m. If that's going to import a .hpp file, whether directly or indirectly, it needs to be compiled as Objective-C++. One way to do it is to rename it .mm, the other is to tell the project not to try to guess language types by file extension.
Tommy and HotLicks gave you the right answer to your immediate problem -- you need to make sure that all source files that include GLView.h are Objective-C files, by naming them .mm.
However, I want to add another side to this. Blindly making all files Objective-C++ is a bad solution. It should lead you to ask yourself: why do all these files need to be Objective-C++, if they are not using C++ features? The answer is that they import GLView.h, and the GLView class contains an instance variable whose type is a pointer to a struct that contains C++ features. Why do these other files care about that? They shouldn't.
There are various things you can do about it.
IRenderingEngine can be forward-declared in GLView.h. It is unnecessary to import IRenderingEngine.hpp, since the header doesn't care about the internal structure of IRenderingEngine; it only needs to know that it's some type in order to have a pointer to it. A forward declaration suffices for this. (However it would be necessary to write struct IRenderingEngine* m_renderingEngine; to be compatible with C.)
Furthermore, the instance variables for the GLView class do not need to be declared in the header in the first place. Instance variables can instead be declared in the implementation (.m) file either in the "class extension" (i.e. #interface GLView () { ... }), or, in newer versions of Xcode, directly in the class implementation (#implementation GLView { ... })

In VS2010 which functions are exported into a DLL?

I am building a DLL to wrap a C/C++ library to be called from matlab.
I am using the standard __declspec(dllexport) to export functions. Specifically, I have several .h files with code that essentially looks like:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
__declspec(dllexport)
#endif
void FOO();
#ifdef __cplusplus
}
#endif
Then, I have a lib.h file, that just includes all these .h files.
#include "foo.h"
#include "bar.h"
My project configuration is such that it does build a DLL, but the mystery is that BAR() is in the DLL (as verified by dumpbin) but FOO is not.
Any ideas on how this could possibly be the case?
In the example above, the problem was due to the fact that BAR did not have a definition in the source tree of the project.
I'm relatively new to TFS and VS, so let me see if I can explain this in a way that makes sense.
The solution has multiple projects. One project is called MatlabDLL, the main project is called OurLibrary. The Matlab DLL is not importing all of Library, just wraps parts of it for inclusion into Matlab. In many cases, Matlab DLL can easily call directly to the C functions, in other cases, functions have to be rewritten to handle Matlab C/DLL calling semantics.
So, BAR had to have a Matlab specific C wrapper around it to enable it to be called from Matlab. The associated source file bar.cpp was in the MatlabDLL project. (Under the hood, BAR calls a number of functions whose source lives in the OurLibrary project, none of whose source files are in the MatlabDLL project.)
FOO had an implementation that did not require a C specific wrapper, so foo.cpp lived in the OurLibrary part of the source tree, and had no source files in the MatlabDLL project, although it's associated .h file was referenced by MatlabDLL.h.
In the end, VS2010 appears to only build the __declspec(dllexport)'d functions that have associated c files in the project. Adding foo.c to the project fixed the problem.

Setting label text from other header files in Visual C++ 2010 .rc file

Assume that you have a label in a legacy Visual C++ 2010 project, defined like so:
[foo.rc]
LTEXT "Foo",IDC_STATIC,42,42,42,42
In a resource (.rc) file.
Now, you want to generate the text based on constants you define in a header file, like so:
[foo.rc]
LTEXT FOO_TEXT,IDC_STATIC,42,42,42,42
Where FOO_TEXT was previously defined in some other way, for instance:
[bar.h]
#define FROBNICATE "F"
#define OO "o"
#define ICANTTHINKOFMETASYNTACTICVARIABLESBEGINNINGWITHO "o"
#define FOO_TEXT (FROBNICATE OO ICANTTHINKOFMETASYNTACTICVARIABLESBEGINNINGWITHO)
Only that that doesn't work, because .rc files are not header files, and the RC compiler complains, telling you:
[Build output]
1>foo.rc(42): error RC2116: expecting number for ID
1>
1>
1>foo.rc(42): error RC2108: expected numerical dialog constant
What would you do?
To clarify, yes, the entire string in question is known at compile-time, but it also needs to be constructed from smaller strings (in this case, version information and release category (development, release, and another one)). Of course, I could also write C++ code that does that, but that seems very inelegant to me.
So, is there a nicer way?
I don't think you will be able to achive what you want without C++ code. See the comment to this msdn article:
Don't use parens in #define
The resource compiler is very limited in its understanding of directives. So, for example, this:
#define RESTYPE_FILE (256)
will silently get ignored, while this:
#define RESTYPE_FILE 256
will work. Obviously, trying to use expressions or anything complicated like that will silently fail, leaving you wondering why you can't load that resource.

Resources