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.
Related
I was able to compiled the gateway but I got the error below running the make command.
gcc -D_REENTRANT=1 -I. -Igw -g -O2 -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_LARGE_FILES= -I/usr/include/libxml2 -I/usr/include/mysql -o gwlib/dbpool.o -c gwlib/dbpool.c
In file included from /usr/include/x86_64-linux-gnu/bits/libc-header-start.h:33,
from /usr/include/stdlib.h:25,
from gwlib/gwlib.h:70,
from gwlib/dbpool.c:70:
/usr/include/features.h:187:3: warning: #warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" [-Wcpp]
187 | # warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"
In file included from gwlib/gwlib.h:83,
from gwlib/dbpool.c:70:
gwlib/dbpool_mysql.c: In function ‘mysql_select’:
gwlib/dbpool_mysql.c:224:48: error: ‘my_bool’ undeclared (first use in this function); did you mean ‘xr_bool’?
224 | bind[i].is_null = gw_malloc(sizeof(my_bool));
gwlib/gwmem.h:122:43: note: in definition of macro ‘gw_malloc’
122 | #define gw_malloc(size) (gw_native_malloc(size))|
gwlib/dbpool_mysql.c:224:48: note: each undeclared identifier is reported only once for each function it appears in
224 | bind[i].is_null = gw_malloc(sizeof(my_bool));
gwlib/gwmem.h:122:43: note: in definition of macro ‘gw_malloc’
122 | #define gw_malloc(size) (gw_native_malloc(size))
make: *** [Makefile:230: gwlib/dbpool.o] Error 1`
This error comes when you're compiling with mysql 8
To fix this, add these lines to gwlib/dbpool_mysql.c
/* define my_bool for newer versions because they use the bool or int C type instead */
#if MYSQL_VERSION_ID >= 80000 && !defined(MARIADB_BASE_VERSION)
typedef bool my_bool;
#endif
I'm trying to assemble a file that uses ARM's CRC instruction. The assembler is producing an error Error: selected processor does not support 'crc32b w1,w0,w0'.
There are runtime checks in place, so we are safe with the instruction. The technique works fine on i686 and x86_64. For example, I can assemble a file that uses Intel CRC intrinsics or SHA Intrinsics without -mcrc or -msha (and on a machine without the features).
Here is the test case:
$ cat test.cxx
#include <arm_neon.h>
#define GCC_INLINE_ATTRIB __attribute__((__gnu_inline__, __always_inline__, __artificial__))
#if defined(__GNUC__) && !defined(__ARM_FEATURE_CRC32)
__inline unsigned int GCC_INLINE_ATTRIB
CRC32B(unsigned int crc, unsigned char v)
{
unsigned int r;
asm ("crc32b %w2, %w1, %w0" : "=r"(r) : "r"(crc), "r"((unsigned int)v));
return r;
}
#else
// Use the intrinsic
# define CRC32B(a,b) __crc32b(a,b)
#endif
int main(int argc, char* argv[])
{
return CRC32B(argc, argc);
}
And here is the result:
$ g++ test.cxx -c
/tmp/ccqHBPUf.s: Assembler messages:
/tmp/ccqHBPUf.s:23: Error: selected processor does not support `crc32b w1,w0,w0'
Placing the ASM code in a source file and compiling with different options is not feasible because CRC32B will be used in C++ header files, too.
How do I get GAS to assemble the instruction?
GCC's configuration and options are the reason we are trying to do things this way. User's don't read manuals, so they won't add -march=armv8-a+crc+crypto -mtune=cortex-a53 to CFLAGS and CXXFLAGS.
In addition, distros compile to a "least capable" machine, so we want the hardware acceleration routines available. When the library is provided by a distro like Linaro, both code paths (software CRC and hardware accelerated CRC) will be available.
The machine is a LeMaker HiKey, which is ARMv8/Aarch64. It has an A53 processor with CRC and Crypto (CRC and Crypto is optional under the architecture):
$ cat /proc/cpuinfo
Processor : AArch64 Processor rev 3 (aarch64)
processor : 0
...
processor : 7
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: AArch64
GCC lacks most of the usual defines one expects to be present by default:
$ g++ -dM -E - </dev/null | sort | egrep -i '(arm|neon|aarch|asimd)'
#define __aarch64__ 1
#define __AARCH64_CMODEL_SMALL__ 1
#define __AARCH64EL__ 1
Using GCC's -march=native does not work on ARM:
$ g++ -march=native -dM -E - </dev/null | sort | egrep -i '(arm|neon|aarch|asimd)'
cc1: error: unknown value ‘native’ for -march
And Clang:
$ clang++ -dM -E - </dev/null | sort | egrep -i '(arm|neon|aarch|asimd)'
#define __AARCH64EL__ 1
#define __ARM_64BIT_STATE 1
#define __ARM_ACLE 200
#define __ARM_ALIGN_MAX_STACK_PWR 4
#define __ARM_ARCH 8
#define __ARM_ARCH_ISA_A64 1
#define __ARM_ARCH_PROFILE 'A'
#define __ARM_FEATURE_CLZ 1
#define __ARM_FEATURE_DIV 1
#define __ARM_FEATURE_FMA 1
#define __ARM_FEATURE_UNALIGNED 1
#define __ARM_FP 0xe
#define __ARM_FP16_FORMAT_IEEE 1
#define __ARM_FP_FENV_ROUNDING 1
#define __ARM_NEON 1
#define __ARM_NEON_FP 0xe
#define __ARM_PCS_AAPCS64 1
#define __ARM_SIZEOF_MINIMAL_ENUM 4
#define __ARM_SIZEOF_WCHAR_T 4
#define __aarch64__ 1
GCC version:
$ gcc -v
...
gcc version 4.9.2 (Debian/Linaro 4.9.2-10)
GAS version:
$ as -v
GNU assembler version 2.24 (aarch64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.24
This answer came from Jiong Wang on the Binutils mailing list. It bypasses GAS's architectural requirements and plays well with GCC:
__inline unsigned int GCC_INLINE_ATTRIB
CRC32W(unsigned int crc, unsigned int val)
{
#if 1
volatile unsigned int res;
asm ("\n"
"\t" ".set reg_x0, 0\n"
"\t" ".set reg_x1, 1\n"
"\t" ".set reg_x2, 2\n"
"\t" ".set reg_x3, 3\n"
"\t" ".set reg_x4, 4\n"
"\t" ".set reg_x5, 5\n"
"\t" ".set reg_x6, 6\n"
"\t" ".set reg_x7, 7\n"
"\t" "#crc32w %w0, %w1, %w2\n"
"\t" ".inst 0x1ac04800 | (reg_%2 << 16) | (reg_%1 << 5) | (reg_%0)\n"
: "=r"(res) : "r"(crc), "r"(val)
);
return res;
#else
volatile unsigned int res;
asm (".cpu generic+fp+simd+crc+crypto \n"
"crc32w %w0, %w1, %w2 \n"
: "=r"(res) : "r"(crc), "r"(val));
return res;
#endif
}
The second one commented out by the preprocessor block was suggested by Nick Clifton on the Binutils mailing list. The idea is GCC generates code using the ISA based on -march=XXX, so it does not matter if we increase capabilities to get past the assembler. We decided to go with Wang's answer because we did not want potential side effects from modifying the .cpu.
And the verification with GCC 4.8 and Binutils 2.24:
$ g++ -O1 test.cxx -c
$ objdump --disassemble test.o
test.o: file format elf64-littleaarch64
Disassembly of section .text:
0000000000000000 <main>:
0: 12001c01 and w1, w0, #0xff
4: 1ac14800 crc32w w0, w0, w1
8: d65f03c0 ret
The #pragma here doesn't seem to have any effect. The code compiles without any warnings:
#pragma GCC diagnostic warning "-Wformat"
#include <stdio.h>
int main()
{
int i = 5;
char s[] = "test";
/* missing argument */
printf("%s");
printf("%d %s", i);
/* missing format specifier */
printf("%s", s, i);
/* type mismatch */
printf("%d", s);
printf("%s", i);
return 0;
}
There are warnings when using the -Wformat option on the command-line:
[user#host test]$ gcc -c test.c
[user#host test]$ gcc -Wformat -c test.c [A
gcc: [A: No such file or directory
test.c: In function 'main':
test.c:11: warning: too few arguments for format
test.c:12: warning: too few arguments for format
test.c:14: warning: too many arguments for format
test.c:16: warning: format '%d' expects type 'int', but argument 2 has type 'char *'
test.c:17: warning: format '%s' expects type 'char *', but argument 2 has type 'int'
It seems if I change the #pragma to make it an error, then it also only has an effect when using the -Wformat command-line parameter:
#pragma GCC diagnostic error "-Wformat"
So then the output looks like:
[user#host test]$ gcc -c test.c
[user#host test]$ gcc -Wformat -c test.c
test.c: In function 'main':
test.c:11: error: too few arguments for format
test.c:12: error: too few arguments for format
test.c:14: warning: too many arguments for format
test.c:16: error: format '%d' expects type 'int', but argument 2 has type 'char *'
test.c:17: error: format '%s' expects type 'char *', but argument 2 has type 'int'
Is there a way to enable format string checking, at all, regardless if making it an error or warning, entirely from C code, and not require the -Wformat command-line parameter?
I share a simple Makefile between Linux and AIX, and it's easier to do conditional compilation purely from code.
I'm trying to compile GCC 4.7.2 on a Buffalo LinkStation Pro Duo (after unlocking it) which runs Linux 2.6.31.8 armv5tel.
Unfortunately, make throws quite some errors, starting with
gcc -c -DIN_GCC_FRONTEND -g -fkeep-inline-functions -DIN_GCC -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-formIn file included from ../../gcc-4.7.2/gcc/tree.h:32,
from ../../gcc-4.7.2/gcc/c-lang.c:27:
../../gcc-4.7.2/gcc/real.h:53: error: 'SIZEOF_LONG' undeclared here (not in a function)
In file included from ../../gcc-4.7.2/gcc/tree.h:32,
from ../../gcc-4.7.2/gcc/c-lang.c:27:
../../gcc-4.7.2/gcc/real.h:87:5: error: division by zero in #if
../../gcc-4.7.2/gcc/real.h:87:5: error: division by zero in #if
../../gcc-4.7.2/gcc/real.h:90:6: error: division by zero in #if
Line 53 of real.h reads unsigned long sig[SIGSZ];, where SIGSZ is defined at line 40 as
#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
while line 87 is #if REAL_WIDTH == 1 with REAL_WIDTH defined starting at line 72 as
#define REAL_WIDTH \
(REAL_VALUE_TYPE_SIZE/HOST_BITS_PER_WIDE_INT \
+ (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */
This seems to boil down to the HOST_BITS_PER_* being zero. Do I have to define these manually with some configure parameter or how can this issue be resolved?
update
config.log contains the following errors:
conftest.c:10:19: error: ppl_c.h: No such file or directory
conftest.c: In function 'main':
conftest.c:16: error: 'choke' undeclared (first use in this function)
conftest.c:16: error: (Each undeclared identifier is reported only once
conftest.c:16: error: for each function it appears in.)
conftest.c:16: error: expected ';' before 'me'
configure:5708: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME ""
| #define PACKAGE_TARNAME ""
| #define PACKAGE_VERSION ""
| #define PACKAGE_STRING ""
| #define PACKAGE_BUGREPORT ""
| #define PACKAGE_URL ""
| #define LT_OBJDIR ".libs/"
| /* end confdefs.h. */
| #include "ppl_c.h"
| int
| main ()
| {
|.
| #if PPL_VERSION_MAJOR != 0 || PPL_VERSION_MINOR < 11
| choke me
| #endif
|.
| ;
| r
Following this post I seem to have forgotten to install ppl, which I'll try now
SIZEOF_LONG should be #defined by configure in the file auto-host.h. Your auto-host.h should contain something like:
/* The size of `long', as computed by sizeof. */
#ifndef USED_FOR_TARGET
#define SIZEOF_LONG 8
#endif
If the above is not present (and it looks like in your case it's indeed so), check config.log for errors. Search for errors around the string checking size of long.
Thanks to chill's answer I checked config.log to discover
conftest.c:10:19: error: ppl_c.h: No such file or directory
(which, curiously, did not prevent configure from creating a Makefile and returning a success error code). The first google hit on that was this post, showing I didn't provide the ppl dependency.
The ppl-1.0 compilation greeted me with
checked_float.inlines.hh:1012: error: 'frexpl' was not declared in this scope
which led me to this post suggesting I'd use the 1.1 snapshot instead, which worked
Now, gcc's make offered me another "helpful" error:
gcc/../libcpp/include/line-map.h:66: error: 'CHAR_BIT'
which turned out to be due to C_INCLUDE_PATH ending with a colon (I already experienced the checking LIBRARY_PATH variable... contains current directory error mentioned in that post, but didn't think about checking other variables for that as well)
Compilation is still running, so far no more errors...
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