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.
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.
Which is to say:
$ cp /usr/cat c
$ ./c
(different window)
$ echo foo > c
-bash: c: Text file busy
$ echo $?
1
Technically, internally the actual write returned -ETXTBSY (-26). Is there a way to get that code instead of 1 with regular bash tools? Short of parsing the text or writing a short C program (this is in a weirdly controlled environment).
Is there a way to get that code
You can write a builtin module that prints errno.
The following source code saved as geterrno.c:
#include <config.h>
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include "posixstat.h"
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include "posixtime.h"
#include "bashansi.h"
#include "shell.h"
#include "builtins.h"
#include "common.h"
#include "bashgetopt.h"
static int geterrno_builtin(WORD_LIST *list) {
printf("%d\n", errno);
return (EXECUTION_SUCCESS);
}
static char *doc[] = {
"geterrno: prints errno",
NULL
};
struct builtin geterrno_struct = {
"geterrno",
geterrno_builtin,
BUILTIN_ENABLED,
doc,
"getrrno: prints errno",
0,
};
compiled and loaded with:
$ gcc -DHAVE_CONFIG_H -DSHELL -I/usr/include/bash -I/usr/include/bash/include -I/usr/include/bash/builtins -I/usr/lib/bash -fPIC -shared -o libgeterrno.so
$ enable -f ./libgeterrno.so geterrno
After that, you can potentially with a lot of luck:
$ geterrno ; echo a > c ; geterrno
0
bash: c: Text file busy
26
with regular bash tools?
No, that is impossible.
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)"
I'm trying out some examples from O'Reilly Flex & Bison. The first Bison and Flex program I'm trying gives me next error when linking the sources:
Undefined symbols for architecture x86_64: "_yylval", referenced
from:
_yylex in lex-0qfK1M.o
As I'm new to Mac and I'm just trying the examples, I have no clue what's wrong here.
l file:
/* recognize tokens for the calculator and print them out */
%{
#include "fb1-5.tab.h"
%}
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n { return EOL; }
[ \t] { /* Ignore whitespace */ }
. { printf("Mystery character %c\n", *yytext); }
%%
y file:
/* simplest version of calculator */
%{
#include <stdio.h>
%}
/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL
%%
calclist: /* nothing */ matches at beginning of input
| calclist exp EOL { printf("= %d\n", $1); } EOL is end of an expression
;
exp: factor default $$ = $1
| exp ADD factor { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
;
factor: term default $$ = $1
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: NUMBER default $$ = $1
| ABS term { $$ = $2 >= 0? $2 : - $2; }
;
%%
main(int argc, char **argv)
{
yyparse();
}
yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
Command line:
bison -d fb1-5.y
flex fb1-5.l
cc -o $# fb1-5.tab.c lex.yy.c -ll
I use -ll instead of -lfl because apparently on Mac os x, the fl library isn't there.
Output:
Undefined symbols for architecture x86_64:
"_yylval", referenced from:
_yylex in lex-0qfK1M.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any ideas?
I caused a similar error by compiling a lex file that began
%{
#include "y.tab.h"
%}
using the command
gcc -ll lex.yy.c
This worked:
gcc -ll y.tab.c lex.yy.c
What's going on? There's a declaration in y.tab.h
extern int yylval
which allows lex.yy.c to compile. However, lex.yy.o needs to be linked against an object file that includes yylval, such as y.tab.o
Apparently the Flex & Bison book from O'Reilly is full of errors.
See http://oreilly.com/catalog/errataunconfirmed.csp?isbn=9780596155988
Very weird that they do not even bother test their own examples...
Part of the question is solved in Undefined reference to yyparse (flex & bison) but not everything. See the errataunconfirmed page.
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