GCC: How to customising warning and errors generated from compilation - c++

My Usecase:
I have two c language files: ApplicationCode.c and UserCode.c . Application code is something generated by my app and UserCode is available to my application user where he can write his own code.
ApplicationCode.c internally uses UserCode.c and calls out its methods/function.
One thing you can assume here that ApplicationCode.c will never have any errors but could have warnings generated by gcc compiler. And UserCode.c can have both errors and warnings.
So, While compiling code I wanted to show user his code's errors as first priority. If needed to show warning also then show warning generated by his code only not from ApplicationCode.c (As i don't want to expose my ApplicationCode.c's code).
One more constraint is here that I wanted to show return-type warning as error here and for this I am using -Werror=return-type argument.
So, I am thinking of following three approaches to do this:
If I could able to disable all the warnings and enable only -Wreturn-type
Raised a saparate question for this here
If I could able to instruct gcc (or redirect) only error messages to stderr and rest on stdout.
Raised a saparate question for this also here
If I could able to disable all the warnings (which are enabled by default) from ApplicationCode.c file and enable all with -Werror=return-type for UserCode.c
I tried searching everywhere but did not get any solution for all the above 3. Let me know how could I achieve above problems or if there any other better way to do solve my use case ?
Update 1:
Here is my both the code file look like
ApplicationCode.c
#include <stdio.h>
// some headers
// some application specific code
int testUserFunction(); // user function declaration
int main(int argc, char *a[]) {
int result = testUserFunction(); // calling user function
// some logic to use and evaluate result
}
UserCode.c
#include<stdio.h>
int testUserFunction(int input1)
{
// user will write his code below this
// user code
}
Base command to compile code:
gcc -o code.out ApplicationCode.c UserCode.c

or if there any other better way to do solve my use case ?
If you don't want to "expose ApplicationCode.c", then why are you showing its compilation output in the first place? Solution: Compile it in somewhere secret and let the user link their UserCode.c with it.

Related

Visual Studio 2017: Ruleset won't execute

I want to define a custom set of rules to be checked at compile time. But it seems not to work.
Example:
I choose one rule directly and I'll get the expected warning.
But when I instead create a custom ruleset containing the exact same rule then I won't get the expected warning.
What could be wrong?
Edit:
void f(std::string& i) {
std::string s = i;
cout << s;
}
int main()
{
std::string s ("abc");
f(s);
}
This gives me the expected warning Warnung C26460 The reference argument 'i' for function 'f' can be marked as const (con.3). in the first case.
Even if I create a custom ruleset including all available rules, I won't get any warnings.
Here you see me selecting the custom ruleset:
Edit: The ruleset action must change one time to enable it.
When I create a new ruleset containing only the const-checks then I will get a .ruleset that does not work and look like this:
In the ruleset editor it looks like this:
When I then change its action from Warning to Error:
Then the .ruleset gets additional lines for each test case:
When I change the action back to warning it looks like this:
Now it is working as expected.
I've been able to reproduce your error with Visual Studio 2017. I don't know exactly what I changed (or if I changed anything at all), but I am able to see the code analysis warning you expect with a custom rule set.
Things I would try:
Double check the Error List window is visible and not hiding somewhere.
Open the rule set file, change the Action to Error and then back to Warning and save it. I wouldn't expect this to be the problem but it's one of the things I did and after which I started seeing the Error List window.

Is there any way to make Visual Studio C++ error output useful?

I find VS19 output quite useless when working on C++ project. Consider running the example code on freshly installed VS19:
#include <iostream>
using namespace std;
class My
{
public:
void f() noexcept
{
throw exception{"A problem sir!"};
}
};
int main()
{
try
{
My m;
m.f();
}
catch (exception& ex)
{
cout << "exception caught! " << ex.what() << endl;
}
return 0;
}
What I would like to receive is: "Function throws an exception while marked as noexcept", and the cursor set on the problematic line. What I get is a new window with some general text, none of which mentions the problem, or where the problem is.
What compiler warning level have you specified? If I use the /W0 option there is no diagnostic but with any other value, /W1 through /W4, the compiler outputs the following lines:
1>filename.cpp(9,1): warning C4297: 'My::f': function assumed not to throw an exception but does
1>filename.cpp(9,1): message : __declspec(nothrow), throw(), noexcept(true), or noexcept was specified on the function
Note: the diagnostic messages include the line and column numbers. If you double-click the error message it moves the cursor to the offending line.
Your verbosity parameter of MSBuild is may be too high. Go to menu: Tools -> Options. Then on the left pane select: Projects and Solutions -> Build and Run.
There you can select the appropriate verbosity of MSBuild (from Quiet to Diagnostic)
Trying to resolve your puzzle in your question:
What I get is a new window with some general text, none of which
mentions the problem, or where the problem is.
I find 90% of output useless for me.
I think what you mean is the Output window, it is always used to display output about build process.
Also, You can also program your own applications to write diagnostic messages at run time to an Output pane. To do this, use members of the Debug class or Trace class in the System.Diagnostics namespace of the .NET Framework Class Library.
For those large solution or large project, which has plenty of resource files. The build sometimes fail with unknown error. The output window is necessary for trouble-shooting.
If you think most of its info is useless,like P.PICARD suggests: Go Tools=>Projects and Solutions=>Build and Run to set its build output verbosity(!Not build log file verbosity) I suggest you change it to Minimal.
If you have a failed build and want to watch the details of the whole build process. Change it to Detailed and rebuild the project or solution.
What I would like to receive is: "Function throws an exception while
marked as noexcept", and the cursor set on the problematic line.
Have you checked the Error List window? If it disappeared,choose View > Error List, or press Ctrl++E.
Add two lines to your code sample:
int main()
{
int a = 2;
int b;
...
}
Navigate to the Error List window(I suggest you set it as Build and Intellisense):
I think it's what you want. And error list window also indicates the Variable which is not initialized or not referenced for improving your coding.
Also, you can see their line numbers. And Double-click the error message, the cursor will navigate to that line.
For C++ program, the warning level is from w0 to w4, you can set it w4 to get the high warning level.(By default it should be w3)
Right-click project=>properties=>Configuration Properties=>C/C++=>Warning Level to set it. (Have been described by Blastfurance, thanks to him!)
Change it to w0, nothing shows. Change it to w3, and it will show warnings about My::f and b but not a.(Actually I don't think you make changes to that, because w3 is by default) Change it to w4 then get the high warning level and all associated warnings display.

In a clang plugin, how do you see whether there was an error compiling the translation unit?

I want my clang plugin to not actually do anything if there was an error compiling the code for the AST my plugin is going to run on.
However, I can't figure out what object contains the list of errors generated during compilation.
Is there either a boolean query for whether there was an error or a list API for getting all the errors (or all diagnostics) generated during the TU compilation?
Thank you.
I eventually figured out a way to get the error count from a CompilerInstance object:
auto & ast_context = compiler_instance.getASTContext();
auto & diagnostics_engine = ast_context.getDiagnostics();
auto diagnostic_consumer = diagnostics_engine.getClient();
auto error_count = diagnostic_consumer->getNumErrors();
if (error_count > 0) {
llvm::report_fatal_error("Errors during compilation, plugin aborting");
}
I don't know if this is the best way, but it is working for me when I put the above code in the onStartOfTranslationUnit of my class I derive from ast_matchers::MatchFinder::MatchCallback.

llvm irbuilder call instruction throwing exception on function inlining pass

I'm new to LLVM. I am using the clang c++ API to compile multiple stub files (in c) to IR, and then stick them together using IR builder (after linking them) to eventually run via JIT.
All this works great, unless I add a functionInlining pass to my optimizations, at which point one of these function calls made in IR builder will trigger the following exception when the pass manager is run:
Assertion failed: (New->getType() == getType() && "replaceAllUses of value with new value of different type!"), function replaceAllUsesWith, file /Users/mike/Development/llvm/llvm/lib/IR/Value.cpp, line 356.
This is how I make the call instruction (pretty straight forward):
Function *kernelFunc = mModule->getFunction( (kernel->Name() + StringRef("_") + StringRef(funcName)).str());
if (kernelFunc){
CallInst* newInst = builder.CreateCall(kernelFunc, args);
}
Later the module is optimized:
legacy::PassManager passMan;
PassManagerBuilder Builder;
Builder.OptLevel = 3;
//Builder.Inliner = llvm::createFunctionInliningPass(); //commenting this back in trigger the exception
Builder.populateModulePassManager(passMan);
passMan.run( *mModule ); //exception occurs before this call returns
Any ideas what to look for?
Try running llvm::verifyModule on your module to see if it's correct. You might have an error and have been getting lucky beforehand but it tripped something up in the inliner.
In general assertions check a subset of things that can be wrong with your module but verify checks a lot more.
It could be a bug in LLVM but more than likely it's a bad module, it's easy to happen.
So I finally setup my dev environment so I could inspect the assertion call in the debugger. I turns out the basic block being replaced had a different context set than the one it was being replaced with. going back and making sure IRBuilder was using the same context as the IR parsers solved the problem.

Including C++ headers in user mode programs built with NT DDK

So...I have a kernel mode component and a user mode component I'm putting together using the turnkey build environment of the NT DDK 7.1.0. The kernel component is all .c/.h/.rc files. The user mode component is .cpp/.c/.h/.rc files.
At first it seemed simplest to use build for both, as I saw you could modify the ./sources file of the user mode component to say something like:
TARGETNAME = MyUserModeComponent
TARGETTYPE = PROGRAM
UMTYPE = windows
UMENTRY = winmain
USE_MSVCRT = 1
That didn't seem to cause a problem and so I was pleased, until I tried to #include <string> (or <memory>, or whatever) Doesn't find that stuff:
error C1083: Cannot open include file: 'string': No such file or directory
Still, it's compiling the user mode piece with C++ language semantics. But how do I get the standard includes to work?
I don't technically need to use the DDK build tool for the user mode piece. I could make a visual studio solution. I'm a bit wary as I have bumped into other annoyances, like the fact that the DDK uses __stdcall instead of __cdecl by default... and there isn't any pragma or compiler switch to override this. You literally have to go into each declaration you care about and change it, assuming you have source to do so. :-/
I'm starting to wonder if this is just a fractal descent into "just because you CAN doesn't mean you SHOULD build user mode apps with the DDK. Here be dragons." So my question isn't just about this particular technical hurdle, but rather if I should abandon the idea of building a C++ user mode component with the DDK tools...just because the kernel component is pure C.
To build a user mode program with WINDDK you need to add some variables to your SOURCES file:
386_STDCALL=0 to use cdecl calling convention by default
USE_STL=1 to use STL
USE_NATIVE_EH=1 to add a support for exception handling
Everything else you already have.
I'll put my full SOURCES file for reference:
TARGETNAME = MyUserModeComponent
TARGETTYPE = PROGRAM
TARGETPATH = obj
UMTYPE = console
UMENTRY = main
USE_MSVCRT = 1
USE_NATIVE_EH=1
USE_STL=1
386_STDCALL=0
SOURCES= main.cpp
And main.cpp:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "bla bla bla!";
cout << s;
return 0;
}
Have fun!
Quick Answer
Abandon the idea of building user-mode components with DDK tools (although I find the concept fascinating :-P)
Your kernel mode component should be built separately from the user mode components as a matter of good practice.
Vague thoughts
Off the top of my head, and this really speaking from limited experience...there are a lot of subtle differences that can creep up if you try to mix the two together.
Using your own example of __cdecl vs __stdcall; You have two different calling conventions. _cdecl is all kernel stuff and all of the C++ methods are wrapped around in WINAPI (_stdcall) passing conventions and __stdcall will clean do auto stack clean up and expect frame pointers inserted all over the place. And if you by accident use compiler options to trigger a __fastcall, it would be a pain to debug.
You can definitely hack something together, but do you really want to keep track of that in your user-space code and build environment? UGH I say.
Unless you have very specific engineering reasons to mix the two environments, (and no a unified build experience is not a valid reason, because you can get that from a batch file called buildall.bat) I say use the separate toolchains.