Is there a GCC pragma directive that will stop, halt, or abort the compilation process?
I am using GCC 4.1, but I would want the pragma to be available in GCC 3.x versions also.
You probably want #error:
$ cd /tmp
$ g++ -Wall -DGoOn -o stopthis stopthis.cpp
$ ./stopthis
Hello, world
$ g++ -Wall -o stopthis stopthis.cpp
stopthis.cpp:7:6: error: #error I had enough
File stopthis.cpp
#include <iostream>
int main(void) {
std::cout << "Hello, world\n";
#ifndef GoOn
#error I had enough
#endif
return 0;
}
I do not know about a #pragma, but #error should do what you want:
#error Failing compilation
It will terminate compilation with the error message "Failing compilation".
This works:
#include <stophere>
GCC stops when it can't find the include file. I wanted GCC to stop if C++14 was not supported.
#if __cplusplus<201300L
#error need g++14
#include <stophere>
#endif
While typically #error is sufficient (and portable), there are times when you want to use a pragma, namely, when you want to optionally cause an error within a macro.
Here is an example use which depends on C11's _Generic and _Pragma.
This example ensures var isn't an int * or a short *, but not a const int * at compile time.
Example:
#define MACRO(var) do { \
(void)_Generic(var, \
int *: 0, \
short *: 0, \
const int *: 0 _Pragma("GCC error \"const not allowed\"")); \
\
MACRO_BODY(var); \
} while (0)
#pragma GCC error "error message"
Ref: 7 Pragmas
You can use:
#pragma GCC error "my message"
But it is not standard.
An alternative is to use static_assert:
#if defined(_MSC_VER) && _MSC_VER < 1916
static_assert(false, "MSVC supported versions are 1916 and later");
#endif
Related
This is quite similar to GCC define function-like macros using -D argument but I couldn't find a relation to my use case.
Consider the following code, main.c:
#include <stdio.h>
const char greeting[] = "hello world";
//#define printf(fmt, ...) (0)
int main() {
printf("%s!\n", greeting);
return 0;
}
If I compile and run this, it works as expected:
$ gcc -Wall -g main.c -o main.exe
$ ./main.exe
hello world!
$
Ok, now I want to How to disable printf function? so I uncomment the #define in the code; I get some warnings, but things again work as as expected (as there is no printout):
$ gcc -Wall -g main.c -o main.exe
main.c: In function 'main':
main.c:5:26: warning: statement with no effect [-Wunused-value]
5 | #define printf(fmt, ...) (0)
| ^
main.c:8:5: note: in expansion of macro 'printf'
8 | printf("%s!\n", greeting);
| ^~~~~~
$ ./main.exe
$
Now, go back to the example as originally posted - that is, comment the #define like - and let's try to set that define via the command-line -D argument:
$ gcc -Wall -D'printf(fmt, ...)=(0)' -g main.c -o main.exe
<command-line>: error: expected identifier or '(' before numeric constant
main.c: In function 'main':
<command-line>: warning: statement with no effect [-Wunused-value]
main.c:8:5: note: in expansion of macro 'printf'
8 | printf("%s!\n", greeting);
| ^~~~~~
Well, the command line argument -D'printf(fmt, ...)=(0)' causes the compilation to fail.
Is there any way I can format this macro somehow, so I can set it via the gcc command line using the -D argument? (Bonus: can it be formulated somehow, so it does not raise warnings like "statement with no effect")
EDIT: contents of C:/msys64/mingw64/include/stdio.h lines 366 to 372:
366 __mingw_ovr
367 __attribute__((__format__ (gnu_printf, 1, 2))) __MINGW_ATTRIB_NONNULL(1)
368 int printf (const char *__format, ...)
369 {
370 int __retval;
371 __builtin_va_list __local_argv; __builtin_va_start( __local_argv, __format );
372 __retval = __mingw_vfprintf( stdout, __format, __local_argv );
373 __builtin_va_end( __local_argv );
374 return __retval;
375 }
When you use:
#define printf(fmt, ...) (0)
The preprocessor turns the code into this:
int main() {
(0);
return 0;
}
That free standing (0) is not allowed. However if you define it this way:
#define printf(fmt, ...)
You can also use the command line definition:
"-Dprintf(fmt, ...)="
Everything works.
Is there a reason why the pre-processor strips out attributes when
-U__GNUC__ is specified and there is at least 1 #include directive?
This seems like surprising behaviour to me. Here's an example:
$ cat foo.c
#include <limits.h>
struct S {
int a;
} __attribute__((__packed__));
$ gcc -E -U__GNUC__ foo.c | tail -3
struct S {
int a;
} ;
But if I remove the #include directive (or if I drop -U__GNUC__) then
attributes don't get stripped by the pre-processor which is what I
expect to happen.
$ cat foo2.c
struct S {
int a;
} __attribute__((__packed__));
$ gcc -U__GNUC__ -E foo2.c
# 1 "foo2.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo2.c"
struct S {
int a;
} __attribute__((__packed__));
Is this a gcc bug or is there documentation of this behaviour?
On my platform standard headers indirectly include /usr/include/argp.h. And in argp.h it says
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
...
#endif
I.e. for low values of __GNUC__ and for __STRICT_ANSI__ modes __attribute__ is pre-defined as an empty macro. By undefing __GNUC__ you made it act like 0 in #if contexts. So, the above code turned __attribute__ into an empty macro.
Where is my mistake? How is good compiling?
llvm-gcc p.c -S -emit-llvm
lli p.s
lli: p.s:1:2: error: expected top-level entity
.file "p.c"
^
simple code
cat p.c
#include <stdio.h>
int main()
{
printf("Hello World!\n");
}
Those flags will produce a file name p.ll not p.s. Therefore:
[2:24pm][wlynch#watermelon /tmp] llvm-gcc p.c -S -emit-llvm
[2:25pm][wlynch#watermelon /tmp] ~/Homebrew/opt/llvm/bin/lli p.ll
Hello World!
In Xcode6, what's the "compiler default" for C++ language dialect.
I am using a C++ new feature std:max(a,b,c)
if I use "Compiler Default", it failed to compile.
When I changed to "C++11 or GNUC++11", it compiles fine.
I am wondering if compiler default is C++98?
I ran below code to get - GNU C++ 98.
#include <iostream>
int main()
{
//gnu mode
#ifndef __STRICT_ANSI__
std::cout << "GNU - ";
#endif
// C++ iso standard
#if __cplusplus == 199711L
std::cout << "C++98" << std::endl;
#elif __cplusplus == 201103L
std::cout << "C++11" << std::endl;
#elif __cplusplus > 201103L
std::cout << "C++14" << std::endl;
#endif
}
Macros chosen
__cplusplus - From gcc online documentation
Depending on the language standard selected, the value of the macro is
199711L, as mandated by the 1998 C++ standard; 201103L, per the 2011
C++ standard; an unspecified value strictly larger than 201103L for
the experimental languages enabled by -std=c++1y and -std=gnu++1y.
__STRICT_ANSI__ - From clang user manual
Differences between all c* and gnu* modes => c* modes define
__STRICT_ANSI__
As a side note, __STRICT_ANSI__ for GNU standard differentiation could also be found from this SO answer
$ g++ -E -dM -std=c++11 -x c++ /dev/null >b
$ g++ -E -dM -std=gnu++11 -x c++ /dev/null >a
$ diff -u a b
--- a 2014-12-19 12:27:11.000000000 +0530
+++ b 2014-12-19 12:27:05.000000000 +0530
## -144,6 +144,7 ##
#define __STDC_UTF_16__ 1
#define __STDC_UTF_32__ 1
#define __STDC__ 1
+#define __STRICT_ANSI__ 1
#define __UINTMAX_TYPE__ long unsigned int
#define __USER_LABEL_PREFIX__ _
#define __VERSION__ "4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.54)"
Im using gcc on Linux and creating a shared library for static libraries. I dont want symbols from some static libraries to be exported.
gcc version is 4.8.0.
Im trying this option at gcc command and it's not working:
-Wl,--exclude-libs,libabc.a .
If I use this option, it's removing all the symbols which not what I want.:
-Wl,--exclude-libs,ALL
Can somebody help in how to use --exclude-option and not to export symbols from specific static library, please?
Thanks
Chandra
Please ignore my comment to question, it is incorrect.
Minimal example:
test1.c:
int testvar1;
int test1(void) {
return 1;
}
test2.c:
extern int testvar1;
int test1(void);
int test2(void) {
testvar1 = -1;
return test1() + 2;
}
test.c:
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *lib = dlopen("./libtest2.so", RTLD_NOW);
int (*f)(void) = dlsym(lib, "test2");
printf("%d\n", f());
return 0;
}
Build:
$ gcc -fPIC -c test1.c
$ ar cru libtest1.a test1.o
$ gcc -fPIC -c test2.c
$ gcc -shared -o libtest2.so test2.o -L. -ltest1 -Wl,--exclude-libs,libtest1.a
$ gcc test.c -ldl
$ ./a.out
3
$ readelf --syms -D libtest2.so | grep test1
$