Scan-Build for clang-13 not showing errors - clang

I am using clang 13 to analyze this code:
int f1(){
int a=5;
short b=4;
bool a1=a;//maybe warn
bool b1=b;//maybe warn
if(a1&&b1)return 1;
return 0;
}
class M{
public:
virtual int GetAge(){return 0;}
};
class P:public M{
public:
virtual int GetAge(){return 1;}
P(){GetAge();}//maybe warn
~P(){GetAge();}//maybe warn
};
int main(){
return 0;
}
but when I run scan-build -enable-checker alpha.core.BoolAssignment clang++ a5.cpp
it gives:
scan-build: Using '/usr/lib/llvm-13/bin/clang' for static analysis
scan-build: Analysis run complete.
scan-build: Removing directory '/tmp/scan-build-2021-10-15-191934-7950-1' because it contains no reports.
scan-build: No bugs found.
However I had expected errors from scan-build. What am I doing wrong?

Related

Registering a custom CodeInsight manager to C++Builder without initialization/finalization sections

I'm trying to register a custom CodeInsight manager into C++Builder 10.1.2 Berlin.
Because there's nothing like Objects Pascal's initialization and finalization sections in C++, e.g.
var
codeManagerIndex: Integer;
{...}
initialization
codeManagerIndex := (BorlandIDEServices as IOTACodeInsightServices).AddCodeInsightManager(TMyCodeInsightManager.Create);
finalization
(borlandIDEServices as IOTACodeInsightServices).RemoveCodeInsightManager(codeManagerIndex);
end.
I tried reproducing their behavior with a custom runner class with constructor/destructor:
class Runner
{
public:
int FCodeManagerIndex;
_di_IOTACodeInsightServices CIS;
Runner() {
if (BorlandIDEServices->Supports(CIS))
FCodeManagerIndex = CIS->AddCodeInsightManager(new TMyCodeInsightManager);
}
~Runner() {
if (BorlandIDEServices->Supports(CIS))
CIS->RemoveCodeInsightManager(FCodeManagerIndex);
}
};
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
Runner Run;
return 1;
}
I can compile my simple implementation but when I try to install the package the following things are happening:
1st try: Error message: Can't load package ... mypackage.bpl - A dynamic link library (DLL) initialization routine failed.
2nd try: An exception (C0000005) occured during DllEntryPoint or DllMain in module: ... mypackage.bpl ... then the IDE crashes.
Is this a wrong way to register?
What am I doing wrong here?
P.S. I get a [TLIB Warning] Warning: library was too large for page size, rebuilt with page size 32 warning when compiling, but I'm quite sure that this can't be the reason for my errors. (?)
there's nothing like Objects Pascal's initialization and finalization sections in C++
Actually, there is. In C++Builder, you can use #pragma startup and #pragma exit to execute user-defined functions:
static int FCodeManagerIndex = -1;
void DoRegister() {
_di_IOTACodeInsightServices CIS;
if (BorlandIDEServices->Supports(CIS)) {
FCodeManagerIndex = CIS->AddCodeInsightManager(new TMyCodeInsightManager);
}
}
#pragma startup DoRegister
void DoUnregister() {
_di_IOTACodeInsightServices CIS;
if ((FCodeManagerIndex != -1) && BorlandIDEServices->Supports(CIS)) {
CIS->RemoveCodeInsightManager(FCodeManagerIndex);
}
}
#pragma exit DoUnregister
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
return 1;
}
Alternatively, since you ready declared a class to handle your registration, you can simply move your class variable into global static memory so its constructor runs at startup and destructor runs at shutdown:
class Runner
{
public:
int FCodeManagerIndex;
Runner() : FCodeManagerIndex(-1) {
_di_IOTACodeInsightServices CIS;
if (BorlandIDEServices->Supports(CIS)) {
FCodeManagerIndex = CIS->AddCodeInsightManager(new TMyCodeInsightManager);
}
}
~Runner() {
_di_IOTACodeInsightServices CIS;
if ((FCodeManagerIndex != -1) && BorlandIDEServices->Supports(CIS)) {
CIS->RemoveCodeInsightManager(FCodeManagerIndex);
}
}
};
static Runner Run;
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
return 1;
}
Declaring the class variable inside of _libmain() is useless since the destructor will be called when the variable goes out of scope when _libmain() exits, thus unregistering the manager immediately after registering it. So the variable has to survive for as long as the package is loaded in memory.

Usage of FunctionPass over ModulePass when creating LLVM passes

I've seen quite a numerous amount of examples that go over creating functions passes (e.g. Brandon Holt and Adrian Sampson), but I am curious as to the difficulty in creating a module pass to do these very similar problems. I've tried to implement a module pass to display the global variable names using this example and llvm source code to understand how you have to iterate through members.
I am using a source compiled version of LLVM, and using the example from the above links to add the pass, and then running:
$ clang -Xclang -load -Xclang build/Skeleton/libSkeletonPass.so something.c
Which then returns this gibberish. However, if I implement a functionPass and just use Auto to determine the type to be initialized it's very straight forward and works. Am I just going about printing the global variables the wrong way?
This is a pastebin of the error output from the terminal. link
Skeleton.cpp
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/LLVMContext.h"
using namespace llvm;
namespace {
// Helper method for converting the name of a LLVM type to a string
static std::string LLVMTypeAsString(const Type *T) {
std::string TypeName;
raw_string_ostream N(TypeName);
T->print(N);
return N.str();
}
struct SkeletonPass : public ModulePass {
static char ID;
SkeletonPass() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
for (Module::const_global_iterator GI = M.global_begin(),
GE = M.global_end(); GI != GE; ++GI) {
errs() << "Found global named: " << GI->getName()
<< "\tType: " << LLVMTypeAsString(GI->getType()) << "!\n";
}
return false;
}
};
}
char SkeletonPass::ID = 0;
// Automatically enable the pass.
// http://adriansampson.net/blog/clangpass.html
static void registerSkeletonPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new SkeletonPass());
}
static RegisterStandardPasses
RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
registerSkeletonPass);
something.c
int value0 = 5;
int main(int argc, char const *argv[])
{
int value = 4;
value += 1;
return 0;
}
I was able to figure this out after some extensive github searching. Here is the answer from which I was following a tutorial to help others who may be curious how to implement a Module Pass.

Lua 5.2 "multiple VMs detected"

I have this simple program which i make into dll in Visual C++ 2008 Express:
#include <lua52/lua.h>
#include <lua52/lualib.h>
#include <lua52/lauxlib.h>
#pragma comment(lib,"lua52.lib")
#include <stdio.h>
int needless(lua_State *L)
{
printf("bullshit\n");
return 0;
}
static const struct luaL_Reg noise[] = {
{"needless",needless},
{NULL,NULL}
};
__declspec(dllexport) int __cdecl luaopen_noise(lua_State *L)
{
luaL_newlib(L, noise);
return 1;
}
when I link the resulting dll with "import noise" in lua5.2 interpreter, I get that "multiple lua VMs detected" for reason that eludes me. What should I do to fix make it work?
Lua libraries written in C should not include a copy of the Lua core library.
I don't know Visual C+ but this line is probably the culprit:
#pragma comment(lib,"lua52.lib")

CUDA 5.0: checkCudaErrors fails to find correct "check" method if class has a "check" method

As the cutil.h header is removed from CUDA Samples, some new headers are introduced like helper_cuda.h, helper_functions.h.
One of the main keywords that is used by me was CUDA_CHECK_ERROR, and I think it is replaced with checkCudaErrors.
In most of my code the macro compiles and works well. However when I use it in a class which has a function named check(..), checkCudaErrors function gives compile errors.
Here is an example:
#include <stdio.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <helper_functions.h>
template<typename T>
class Trivial {
public:
void check()
{
}
void initialize()
{
checkCudaErrors(cudaMalloc(NULL, 1));
}
T val;
};
int main(int argc, char **argv)
{
Trivial<int> tt;
tt.initialize();
return 0;
}
and the result of compilation: (the same error is seen when compiled with GCC 4.5 also!)
1>------ Build started: Project: ZERO_CHECK, Configuration: Release x64 ------
2>------ Build started: Project: massivecc, Configuration: Release x64 ------
2> trivial_main.cpp
2>..\src\trivial_main.cpp(19): error C2660: 'Trivial<T>::check' : function does not take 4 arguments
2> with
2> [
2> T=int
2> ]
2> ..\src\trivial_main.cpp(18) : while compiling class template member function 'void Trivial<T>::initialize(void)'
2> with
2> [
2> T=int
2> ]
2> ..\src\trivial_main.cpp(29) : see reference to class template instantiation 'Trivial<T>' being compiled
2> with
2> [
2> T=int
2> ]
3>------ Skipped Build: Project: ALL_BUILD, Configuration: Release x64 ------
3>Project not selected to build for this solution configuration
========== Build: 1 succeeded, 1 failed, 1 up-to-date, 1 skipped ==========
The same error is taken when I removed the template parameter.
I had to copy the check(..) function's definition from helper_functions.h into my class's header to be able to compile the class.
#include <stdio.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <helper_functions.h>
class Trivial {
public:
template< typename T >
bool check(T result, char const *const func, const char *const file, int const line)
{
if (result) {
fprintf(stderr, "CUDA error at %s:%d code=%d(%s) \"%s\" \n",
file, line, static_cast<unsigned int>(result), _cudaGetErrorEnum(result), func);
return true;
} else {
return false;
}
}
void check() { }
void initialize()
{
checkCudaErrors(cudaMalloc(NULL, 1));
}
};
int main(int argc, char **argv)
{
Trivial tt;
tt.initialize();
return 0;
}
So, this mainly solved my problem and my code compiled successfully.
with reference to the source code found in helper_cuda.h on line 680
https://github.com/pathscale/nvidia_sdk_samples/blob/master/vectorAdd/common/inc/helper_cuda.h
you find checkCudaErrors declares a #define checkCudaErrors(val) check ( (val), #val, FILE, LINE ) which takes in a single argument and calls check with 3 other arguments based on config.Note that it is also defined in line 680
Whereas in your case, you define a check that does not take any argument. case of different declaration and definition, multiple definitions.

MSBuild fails to see environment variable that is set from build workflow

This is related to TFS 2010 Build System. Within our build workflow we set a couple of environment variables using the SetEnvironmentVariable method of System.Environment class. I have confirmed that this environment variable gets set properly on the build server and that it gets set as a system wide environment variable.
The problem is that when MSBuild gets invoked within this WF and it compiles the solutions, our post build events which tries to read this environment variable fail as they are unable to see this environment variable.
Is there a way to force MSBuild to reload environment variables or force a running WF to reload environment variables? My suspicion is that even though WF creates this variable, it does not refresh its Environment state and hence can not see the variable. Further since the WF invokes MSBuild, it passes the same environment state to MSBuild which does ont contain this variable.
Update
Stick the following code in Visual Studio and run it. The delay to SendMessageTimeOut is 10 second so be patient.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace EnvironmentVarTest
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool
SendMessageTimeout(
IntPtr hWnd,
int Msg,
int wParam,
string lParam,
int fuFlags,
int uTimeout,
out int lpdwResult
);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SETTINGCHANGE = 0x001A;
public const int SMTO_NORMAL = 0x0000;
public const int SMTO_BLOCK = 0x0001;
public const int SMTO_ABORTIFHUNG = 0x0002;
public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
static void Main(string[] args)
{
Program p = new Program();
string environmentVariableValue = DateTime.Now.ToLongTimeString().Replace(":", String.Empty);
Console.WriteLine("On the CMD window that opens up after about 10 seconds, if you type %samplevar% and hit Enter, you should see: " + environmentVariableValue);
p.SetEnvironmentVariable(environmentVariableValue);
RefreshProcessVars();
p.ReadEnvironmentVariable();
p.StartCMD();
Console.ReadLine();
}
void SetEnvironmentVariable(string value)
{
System.Environment.SetEnvironmentVariable("samplevar", value, EnvironmentVariableTarget.Machine);
}
static void RefreshProcessVars()
{
int result;
bool callresult = SendMessageTimeout(
(System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
"Environment",
SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
10000,
out result);
if (!callresult || result == 0)
{
int lasterror = Marshal.GetLastWin32Error();
Win32Exception winex = new Win32Exception(lasterror);
Console.WriteLine("Exception happened while calling SendMessageTimeOut. The exception message is " + winex.Message);
}
}
void ReadEnvironmentVariable()
{
var x = System.Environment.GetEnvironmentVariable("samplevar", EnvironmentVariableTarget.Machine);
}
void StartCMD()
{
Process.Start("cmd.exe");
}
}
}
Unfortunately, because the MSBuild process is passed a cached version of the environment variables when it's started up, the command-line functionality of that process will not be able to see the updated values. The best bet you've got, in my opinion, is to either change that variable in the post-build event or store the value in a medium that you can read from the post-build event.
Update
Okay, so the statement below (which can be found here) I think explains where the environment variables are coming from and why you're not getting an updated version in MSBuild.
By default, a child process inherits the environment variables of its parent process.
So, two can play at that game, let's just broadcast that a change has occurred and see if that will take care of it for us. Below is the code that should do that for you.
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool
SendMessageTimeout(
IntPtr hWnd,
int Msg,
int wParam,
string lParam,
int fuFlags,
int uTimeout,
out int lpdwResult
);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SETTINGCHANGE = 0x001A;
public const int SMTO_NORMAL = 0x0000;
public const int SMTO_BLOCK = 0x0001;
public const int SMTO_ABORTIFHUNG = 0x0002;
public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
int result;
SendMessageTimeout(
(System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
"Environment",
SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
SomeTimeoutValue,
out result);

Resources