#define NUM 1
#if(NUM)
if(globalglobalInteger){
result = 1;
}
#else
result=2
#endif
Given the above code , the requirement is that the conditional macro #if should not be evaluated and all code under #if and #else should be passed for further processing.
Basically I want both the active and inactive part(code under #if and code under #else) to be present in the clang AST.
Is this possible in clang ?
Is there any pre-processor flag available
for doing this in clang?
Saw that there is flag called -fdirectives-only in gcc which disables macro expansion but could not find similar flag in clang
Preprocessing takes places before parsing and AST generation, so you can't have
non-expanded defines and macros in the AST.
However, there are means for handling non-preprocessed code - such as registering to clang preprocessor callbacks (the PPCallbacks interface) or through the pp-trace tool
(disclamer: I don't have experience with this myself).
References:
Clang AST dump doesn't show #defines
http://clang-developers.42468.n3.nabble.com/Preprocessor-Parser-interaction-td3754583.html
http://www.llvm.org/devmtg/2016-11/Slides/Trull-ExtendingClangASTMatchers.pdf
With regards to flags, clang has no equivalent to gcc's -fdirectives-only. For keeping both parts of the macro in output,
you could disable preprocessing altogether, similar to gcc's -fpreprocessed - which will effectively disable macro expansion (but still macros will be absent from the AST).
You could insepct the AST generated for non-preprocessed source files with these commands:
clang -xcpp-output -Xclang -ast-dump -c foo.c
clang -xc++-cpp-output -Xclang -ast-dump -c foo.cpp
HTH - good luck!
Related
I would like to make a LibTooling tool that takes precisely the same compilation string as clang. For example
clang a.c -O3 b.c -I/myinclude -DMY_DEFINE c.c. Should be replaced by my-tool a.c -O3 b.c -I/myinclude -DMY_DEFINE c.c
Officially suggested by clang documentation way to parse arguments in LibTooling-based tools is CommonOptionsParser. It expects a different format of command-line string and by default relies on the compile_commands.json file. I can simulate desired behavior if I put all source files before -- and everything else after it, like this: my-tool a.c b.c c.c -- -O3 -I/myinclude -DMY_DEFINE. Is it possible to implement this without such hacking of parameter string using llvm/clang API?
First question here.
I have some troubles with the XCode Build System, specifically with preprocessor definitions.
I'm trying to define a macro for the objective-c runtime to avoid enforcing the dispatch functions to be cast to an appropriate function pointer type. The usual way to go would be to use #define OBJC_OLD_DISPATCH_PROTOTYPES and then include the header on the next line. Once the header gets included, the macro is already defined and the header is configured accordingly.
But that's where it starts to get weird!
The macro is not recognized at all and the header gets included as if the #define statement was not there so it fails to #define OBJC_OLD_DISPATCH_PROTOTYPES and it gets (re?)defined as 0.
main.c
#include <stdio.h>
#define OBJC_OLD_DISPATCH_PROTOTYPES 1
#include <objc/objc-runtime.h>
int main(int argc, const char * argv[]) {
// From there:
// - Build System: OBJC_OLD_DISPATCH_PROTOTYPES is always 0, except if defined in build settings
// - Clang (only): OBJC_OLD_DISPATCH_PROTOTYPES is 1
printf("%d\n", OBJC_OLD_DISPATCH_PROTOTYPES);
}
The build system acts as expected when the preprocessor macro is defined in the project build settings under the "Apple Clang - Preprocessing" section. It defines the global macro using the -D parameter of clang making it available to any files used by the project.
However, source code compiles correctly when I use clang from a terminal using clang main.c.
Could someone tell me what I need to configure for the build system to behave normally?
It gives a warning when building with Xcode IDE:
Ambiguous expansion of macro 'OBJC_OLD_DISPATCH_PROTOTYPES'
and the output is indeed 0 using Xcode directly, but 1 with clang main.c. The difference is that Xcode uses clang with enabled modules by default: You get the same warning on the command line if you enable modules there:
clang -fmodules main.c
Solution
In Xcode, select the target, go to the "Build Settings" tab and in the "Apple Clang - Language - Modules" section, switch the "Enable Modules (C and Objective-C)" entry to 'NO':
Then you get the expected result in both cases, regardless of whether you use Xcode or Clang on the command line.
Explanation:
If you use modules the following happens:
instead of the preprocessor including the text and compiling the result, a binary representation of the module is used
modules are (independently) precompiled, i.e. they use the definitions from the time the module was precompiled
consequently, preprocess definitions from the code before the include/import statement have no effect on the module (nor on other imported modules).
if modules are enabled, not only #imports are affected, but also #includes are translated into module imports under the hood
So you have a contradictory definitions for the OBJC_OLD_DISPATCH_PROTOTYPES.
The precompiled module uses a 0 for OBJC_OLD_DISPATCH_PROTOTYPES and you redefine it as 1.
BTW: if you use
#define OBJC_OLD_DISPATCH_PROTOTYPES 0
then you use the same definition that the precompiled module is using and therefore there is no warning about an ambiguous expansion of the macro even if modules are enabled.
Without enabled modules, the preprocessor includes the text, compiles the result and returns the expected result, i.e. in objc.h the desired typedef are used.
I'm using QtCreator 4.11.2 , installed via MSYS2, with ClangCodeModel enabled.
Here is my program (this is the result of creating a New Non-QT Plain C Application):
#include <stdio.h>
#include <stdbool.h>
_Bool a;
bool b;
int main()
{
printf("Hello World!\n");
return 0;
}
The .pro file is unchanged from the default:
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += \
main.c
The annotation compiler highlights an error saying stdbool.h cannot be found.
But it does not give an error for _Bool a; , so it is clearly running in C99 mode but has some problem with include paths. The "Follow symbol under cursor" option works, opening stdbool.h.
My question is: How do I configure include paths for the annotation compiler or otherwise fix this problem?
I have been unable to figure out how to set options for the annotation compiler or even which compiler binary it is using . Under Tools > Options > C++ > Code Model > Diagnostic Configuration it lets me add -W flags but does not let me add -I flags, a red message pops up saying the option is invalid.
Under Tools > Options > C++ Code Model inspector, there are no diagnostic messages, and the Code Model Inspecting Log shows stdbool.h being correctly found and parsed, as msys64/mingw64/lib/gcc/x86_64-w64-mingw32/9.3.0/include/stdbool.h.
If I disable the ClangCodeModel plugin then there are no errors , but I would like to use the clang version if it can be made to work as in general it has good diagnostics.
The result of clang --version in a shell prompt is:
clang version 10.0.0 (https://github.com/msys2/MINGW-packages.git 3f880aaba91a3d9cdfb222dc270274731a2119a9)
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: F:\Prog\msys64\mingw64\bin
and if I compile this same source code using clang outside of QtCreator, it compiles and runs correctly with no diagnostics. So the annotation compiler is clearly not the same as the commandline clang?
The Kit I have selected in QtCreator is the autodetected Desktop Qt MinGW-w64 64bit (MSYS2)
The exact same symptoms occur if I make a Plain C++ project and try to include stdbool.h (which is required to exist by the C++ Standard, although deprecated), although interestingly it does accept <cstdbool>.
I have found a workaround of sorts: including in the .pro file the line:
INCLUDEPATH += F:/Prog/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/9.3.0/include/
causes the annotation compiler to work correctly, however this is undesirable as I'd have to keep changing it whenever I switch Kits because it also passes this to the actual build compiler, not just the annotation compiler.
Create file stdbool.h in C:\msys64\mingw64\x86_64-w64-mingw32\include and copy paste this code:
/* Copyright (C) 1998-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/*
* ISO C Standard: 7.16 Boolean type and values <stdbool.h>
*/
#ifndef _STDBOOL_H
#define _STDBOOL_H
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#else /* __cplusplus */
/* Supporting _Bool in C++ is a GCC extension. */
#define _Bool bool
#if __cplusplus < 201103L
/* Defining these macros in C++98 is a GCC extension. */
#define bool bool
#define false false
#define true true
#endif
#endif /* __cplusplus */
/* Signal that all the definitions are present. */
#define __bool_true_false_are_defined 1
#endif /* stdbool.h */
Note
Creating a manual file stdbool.h works for me but its a sketchy and a temporary solution for now. Don't use this if you feel its too sketcy. I would rather use a alternative solution than this hack if it exist. This solution might not be good but it still works for me.
I have two LLVM passes, one which requires the outputs of the other. So in PassB I have:
void DiscoPoP::getAnalysisUsage(AnalysisUsage &Info) const{
Info.addRequired<PassA>();
}
I tried adding the snippet below to PassB, but when running clang -Xclang -load -Xclang LLVMPassB.so I get an error: undefined symbol: _ZN18PassA2IDE
static RegisterStandardPasses PassLoader(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new PassA()); });
If I load PassA in clang as well, it works: clang -Xclang -load -Xclang LLVMPassA.so -Xclang -load -Xclang LLVMPassB.so
But it seems redundant to have to load it manually if it required from the PassB. Is there a way to load PassA programmatically from PassB?
I get an error: undefined symbol: _ZN18PassA2IDE
Because the PassA isn't visible to clang.
If I load PassA in clang as well, it works: clang -Xclang -load -Xclang LLVMPassA.so -Xclang -load -Xclang LLVMPassB.so
As expected.
But it seems redundant to have to load it manually if it required from the PassB.
Only if there was a way for clang know know about PassA when passB is supplied as flag. clang has no way of knowing where LLVMPassA.so resides unless we pass as flag.
Is there a way to load PassA programmatically from PassB?
This can be done if you modify the LLVM source code and put both your passes there. Registering a pass within LLVM pass manager is straightforward. See https://reviews.llvm.org/D50658 (Hot cold splitting pass) as an example, specifically changes in lib/Transforms/IPO/PassManagerBuilder.cpp, and function createHotColdSplittingPass.
I am having trouble writing a bison parser, and unexpectedly ran into difficulties getting the parser to print debug information. I found two solutions on the web, but neither seems to work.
This advocates to put this code in the main routine:
extern int yydebug;
yydebug = 1;
Unfortunately the C++ compiler detects an undefined reference to `yydebug'.
This suggests putting
#if YYDEBUG == 1
extern yydebug;
yydebug = 1;
#endif
into the grammar file. It compiles but does not produce output.
What does work is to edit the parser file itself, replacing
int yydebug;
by
int yydebug = 1;
The big disadvantage is that I have to redo this every time I change the grammar file, which during debugging would happen constantly. Is there any other way I can provoke the parser into coughing up its secret machinations?
I am using bison v2.4.1 to generate the parser, with the following command-line options:
bison -ldv -p osil -o $(srcdir)/OSParseosil.tab.cpp OSParseosil.y
Although the output is a C++ file, I am using the standard C skeleton.
With bison and the standard C skeleton, to enable debug support you need to do one of the following:
Use the -t (Posix) or --debug (Bison extension) command-line option when you create your grammar. (bison -t ...)
Use the -DYYDEBUG=1 command-line option (gcc or clang, at least) when you compile the generated grammar (gcc -DYYDEBUG=1 parser.tab.c ...`).
Add the %debug directive to your bison source
Put #define YYDEBUG 1 in the prologue in your bison source (the part of the file between %{ and %}.
I'd use -t in the bison command line. It's simple, and since it is Posix standard it probably will also work on other derived parser generators. However, adding %debug to the bison source is also simple; while it is not as portable, it works in bison 2.4.
Once you've done that, simply setting yydebug to a non-zero value is sufficient to produce debug output.
If you want to set yydebug in some translation unit other than the generated parser itself, you need to be aware of the parser prefix you declared in the bison command line. (In the parser itself, yydebug is #defined to the prefixed name.) And you need to declare the debug variable (with the correct prefix) as extern. So in your main, you probably want to use:
extern int osildebug;
// ...
int main(int argc, char** argv) {
osildebug = 1;
// ...
}
If you're using bison, your best place to find information is the bison manual; most of the above answer will be found in that page.