I am a new learner in Clang and meet an odd bug.
My code is a simple case:
.....
static llvm::cl::OptionCategory MyToolCategory("");
.....
int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
tooling::MyFactory Factory;
Tool.run(newFrontendActionFactory(&Factory));
return 0;
}
but it report an very odd error when compile with clang++(my llvm&clang's version is 3.4):
ToolingTutorial.cpp:74:23: error: no matching constructor for initialization of 'clang::tooling::CommonOptionsParser'
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/acsa-amd2/Documents/llvm-3.4/tools/clang/include/clang/Tooling/CommonOptionsParser.h:67:3: note: candidate constructor not
viable: no known conversion from 'llvm::cl::OptionCategory' to 'const char *' for 3rd argument
CommonOptionsParser(int &argc, const char **argv, const char *Overview = 0);
^
/home/acsa-amd2/Documents/llvm-3.4/tools/clang/include/clang/Tooling/CommonOptionsParser.h:61:7: note: candidate constructor
(the implicit move constructor) not viable: requires 1 argument, but 3 were provided
class CommonOptionsParser {
^
/home/acsa-amd2/Documents/llvm-3.4/tools/clang/include/clang/Tooling/CommonOptionsParser.h:61:7: note: candidate constructor
(the implicit copy constructor) not viable: requires 1 argument, but 3 were provided
1 error generated.
make: *** [ToolingTutorial.o] Error 1
it makes no sense that the constructor is no match and the compiler mistake 'llvm::cl::OptionCategory' for 'const char *' .
Did anyone meet this problem? Thanks!
In the latest LLVM14, CommonOptionsParser's construct functions are declared as protected or private. So, replace these functions with create(...).
llvm::Expected<clang::tooling::CommonOptionsParser> option = CommonOptionsParser::create(argc, argv, FindDeclCategory, llvm::cl::OneOrMore, FindDeclUsage);
auto files = option->getSourcePathList();
clang::tooling::ClangTool tool(option->getCompilations(), files);
return tool.run(clang::tooling::newFrontendActionFactory<DeclFindingAction>().get());
I had the same error in a tutorial, the error message says that there is something wrong with the last argument.
I have checked the official API (http://clang.llvm.org/doxygen/classclang_1_1tooling_1_1CommonOptionsParser.html) and the example given seems to use the same pattern.
But I have also checked my source files (/usr/include/clang/Tooling/CommonOptionsParser.h on Arch) and the declaration of the constructor is not the same.
My clang version is 3.4. The next version is 3.5 and I think that the official documentation
is for the 3.5.
According to the documentation in the source file of the clang 3.4 the last argument seem to be optionnal and you can use:
CommonOptionsParser OptionsParser(argc, argv);
After that I had no errors during the compile time.
Related
In earlier releases of llvm/clang I was able to detect whether global variable was a string by using ie. the GlobalVar->getName() function and checking whether it ends with ".str". I've tried this in the llvm/clang 13 and 14 and it seems that all the names I'm getting are mangled names. Am I missing something?
For example, I have this basic C source code:
//compiled with: clang.exe -std=c99 helloCC.c -o helloCC.exe -mllvm -my_get_strings=1 -flegacy-pass-manager
#include <stdio.h>
char *xmy1 = "hello world";
int main(int argc, char *argv[]) {
printf("%s", xmy1);
return 0;
}
I've manually edited the llvm/clang code too trigger my function as one of the pass (clang executed with "-flegacy-pass-manager" and I've added my pass to PassManagerBuilder.cpp int the void PassManagerBuilder::populateModulePassManager(legacy::PassManagerBase &MPM) function.
Anyway my runOnModule handler executes, iterates over global variables (M.global_being() to M.global_end()) and all the names got by GlobalVar->getName() seems to be mangled:
found global = "??_C#_0M#LACCCNMM#hello?5world?$AA#"
Obviously now my previous theory to detect whether this is a string or not doesn't work. Is there any other better function to detect whether a global is a string / or I am doing something wrong?
I've tried demangling the name, well I can demangle it but I still don't know how to verify whether this is a string or nor. Is there any LLVM function for it?
Well, the main question here is what do you mean by "global variable is string". If you're meaning C-style strings, then you'd just take initializer (which is Constant) and check if this is a C-style string using isCString method (https://llvm.org/doxygen/classllvm_1_1ConstantDataSequential.html#aecff3ad6cfa0e4abfd4fc9484d973e7d)
I am using clang's abstract syntax tree generation to generate an AST for some source files. It maps out normal functions great, however it trips up on some functions, mislabeling them as variable declarations. When it does this it waits for a semicolon to finish this declaration and so does not map out the rest of the source file following the problem function. Is there a way to make clang realize that it's a function definition, not a variable declaration?
I put a semicolon after the function definition and doing that makes clang ignore the contents of the function, but at least it generates nodes for the code following it in the source file. I'm using the prophy python interface to interact with clang in my scripts, but ran clang manually and found the same thing.
This is an example of a function that clang does map:
int killProcess(int pid)
{
int ret=1;
HANDLE pHandle;
if ((pHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid)) != NULL)
if(!TerminateProcess(pHandle,0)) {
ret=0;
CloseHandle(pHandle);
}
return ret;
}
This is an example of a function which clang thinks is a variable declaration and ignores everything after it if there is no semicolon after the closing brace:
DWORD WINAPI listProcessesThread(LPVOID param)
{
char sendbuf[IRCLINE];
LPROC lproc = *((LPROC *)param);
LPROC *lprocp = (LPROC *)param;
lprocp->gotinfo = TRUE;
sprintf(sendbuf,"[PROC]: Listing processes:");
if (!lproc.silent) irc_privmsg(lproc.sock,lproc.chan,sendbuf,lproc.notice);
if (listProcesses(lproc.sock,lproc.chan,lproc.notice,NULL, FALSE, lproc.full) == 0)
sprintf(sendbuf,"[PROC]: Process list completed.");
else
sprintf(sendbuf,"[PROC]: Process list failed.");
if (!lproc.silent) irc_privmsg(lproc.sock, lproc.chan, sendbuf, lproc.notice);
addlog(sendbuf);
clearthread(lproc.threadnum);
ExitThread(0);
}
The expected results would be that clang knows that this is a function and generates a corresponding AST, however it doesn't. It constructs a VAR_DECL node with the spelling "WINAPI" instead of a "FUNCTION_DECL" node. The error it gives upon running "clang -cc1 -ast-dump processes2.cpp" is:
`-VarDecl 0x5625ad7ab2e0 col:7 invalid WINAPI 'int'
1 error generated.
At the end of its log. The abstract syntax tree up until this point is generated and displayed.
NB: I do not have WINAPI library installed because I am working on a Ubuntu machine.
During the conversion process I come across the following C code:
/** Opaque data type for the error object.
*/
typedef struct kError * KErrorRef;
Where is kError declared?
The conversion tool provided by Rudy Velthuis produces this code:
type
{$EXTERNALSYM KErrorRef}
KErrorRef = ^kError;
When I try to compile it, I get this error message:
[dcc32 Error] ukError.pas(50): E2003 Undeclared identifier: 'kError'
What is the appropriate way of converting the C code?
Where is kError declared?
Nowhere, because it is not actually needed.
In this declaration:
typedef struct kError * KErrorRef;
struct kError is an incomplete type, which is allowed when used with a pointer.
The declaration is roughly equivalent to this:
// forward declaration of some as-yet unknown struct type
struct kError;
// this is OK; compiler knows the size of a pointer, which is not
// affected by the size of the actual struct being pointed to
typedef kError *KErrorRef;
The conversion tool provided by Rudy Velthuis produces this code
The tool is not producing the correct Delphi code in this instance. When dealing with a typedef for an incomplete (forward-declared) struct type, it should produce Delphi code more like this instead, if the actual struct type is not declared later on:
type
{$EXTERNALSYM KErrorRef}
KErrorRef = ^kError;
{$NODEFINE kError}
kError = record
end;
I'd declare an empty record and then a pointer to it. That gives you type safety.
type
KErrorRef = ^kError;
kError = record
end;
When running the following command: sourceanalyzer -debug -b $build_id touchless make
I'm getting this error:
Compiling C++ myFile.C
[ERROR]: Translator execution failed. Please consult the Troubleshooting section of the User Manual.
Translator returned status 139:
“/usr/include/c++/4.3/atomicity.h”, line 51: warning identifier
“__sync_fetch_and_add” is undefined
{ return __sync_fetch_and_add(__mem, __val); }
“/usr/include/c++/4.3/atomicity.h”, line 55: warning identifier
“__sync_fetch_and_add” is undefined
{ __sync_fetch_and_add(__mem, __val); }
“/usr/include/c++/4.3/new”, line 95: warning: first parameter of allocation
Function must be of type “size_t”
Void* operator new(std::size_t) throw (std::bad_alloc);
“/usr/include/c++/4.3/new”, line 96: warning: first parameter of allocation
Function must be of type “size_t”
Void* operator new[](std::size_t) throw (std::bad_alloc);
“/usr/include/c++/4.3/new”, line 99: warning: first parameter of allocation
Function must be of type “size_t”
Void* operator new(std::size_t, const std::nothrow_t&) throw ();
“/usr/include/c++/4.3/new”, line 100: warning: first parameter of allocation
Function must be of type “size_t”
Void* operator new[](std::size_t, const std::nothrow_t&) throw ();
“/usr/include/c++/4.3/new”, line 105: warning: first parameter of allocation
Function must be of type “size_t”
Inline void* operator new(std::size_t, void* __p) throw (){ return __p; }
“/usr/include/c++/4.3/new”, line 105: warning: first parameter of allocation
Function must be of type “size_t”
Inline void* operator new[](std::size_t, void* __p) throw (){ return __p; }
“/opt/ilog51/views51/include/ilog/list.h”, line 77: warning: first parameter of allocation function must be of type “size_t”
IL_MLK_DECL();
“/opt/ilog51/views51/include/ilog/list.h”, line 110: warning: no appropriate operator delete is visible
{ e(); delete_first; _first; _first = _last 0; _length = 0; }
Furthermore, when uploading the FPR file to SSC, under Artifacts the status is: Error Processing. And when auditing issues, the ssc is unable to locate source files.
Any ideas about this issues ?
One idea is that the older gcc 4.3 (year 2008?) used compiler built-ins that were specific to GCC, while Fortify relies on Clang to translate the source code.
https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
I have a snippet of code which compiles in C++ Builder XE8 using the classic BCC compiler. However, in Rad Studio 10 Seattle using the Clang compiler I get the error
'no matching constructor found for initialization of TChoiceItem'
Here is the snippet of code which causes the error.
LISTITEM_BEGIN( sch_TYPE_Choice )
LISTITEM_DATA( sch_TYPE_Daily, "Daily" )
LISTITEM_DATA( sch_TYPE_Weekly, "Weekly" )
LISTITEM_DATA( sch_TYPE_Monthly, "Monthly" )
LISTITEM_END()
Here is the code which defines TChoiceItem
//------------------------------------------------------------------------------
#define LISTITEM_BEGIN( Name ) TChoiceItem Name[] = {
//------------------------------------------------------------------------------
#define INT_LISTITEM_BEGIN( Name ) TIntChoiceItem Name[] = {
//------------------------------------------------------------------------------
#define LISTITEM_DATA( XCode, XText ) { XCode, 0, (char*)XText, 0 },
#define LISTITEM_DATA_NC( XShortText, XText ) { 0, (char*)XShortText, (char*)XText, 0 },
#define LISTITEM_DATA_EX( XCode, XShortText, XText ) { XCode, (char*)XShortText, (char*)XText, 0 },
#define LISTITEM_DATA_EX2( XCode, XShortText, XText, XDesc ) { XCode, (char*)XShortText, (char*)XText, (char*)XDesc },
#define LISTITEM_END() LISTITEM_DATA(0,0) };
I am fairly new to C++ so I am not exactly sure what to call the above method of defining a class/method.
Is this some sort of dated language feature not supported by the Clang compiler? Is there a way to modify the code or definition so the compiler will accept it?
Edit:
I found the actual declaration of the TChoiceItem class.
class TChoiceItem : public TChoiceBase
{
public:
char Code;
char *ShortText;
char *Text;
char *Desc;
};
It does't appear to have any sort of standard constructor at all. But somehow, everything still compiles and works with the classic BCC compiler.
Edit 2:
I found this question which looks to be describing a similar issue. Could it be that I need to include some kind of compiler flag when compiling the code? If so can I add a flag somehow in the embarcadero project compiler settings?
Using a list of values in braces to initialize the individual members of a class or struct is known as aggregate initialization.
As explained on cppreference.com, aggregate initialization isn't permitted if the class has a base class (among other restrictions). TChoiceItem inherits from TChoiceBase, so aggregate initialization isn't allowed (and the "classic" bcc32 compiler shouldn't have allowed it).
You have a couple of choices:
First, you can change the code to not inherit from TChoiceBase.
Second, you can define a constructor:
TChoiceItem(char code, char *short_text, char *text, char *desc)
: Code(code), ShortText(short_text), Text(text), Desc(desc) {}
C++11's uniform initialization means that your macros' syntax doesn't have to change: instead of braces meaning a list of values for individual members, the braces will mean a list of parameters to the constructor, but the result will be the same.