I want to compile a time error checking as mentioned below . But I am not able to find out how to use it inside main()?
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
int main(){
BUILD_BUG_ON_NULL(12);
}
Below is the mentioned error
1--error C2332: 'struct' : missing tag name
2--error C2143: syntax error : missing ')' before '{'
3--error C2027: use of undefined type 'main::<unnamed-tag>'
4--error C2143: syntax error : missing ';' before '{'
5--error C2059: syntax error : ')'
Can anyone please let me know what I am doing wrong?
EDIT: the question was originally tagged as C++, but now as just C.
I'm not going to chase further fundamental changes of the question.
Original answer for the C++ tagged question:
This source code:
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
int main(){
BUILD_BUG_ON_NULL(0);
}
compiled with g++ 4.7.1., produced
foo.cpp: In function 'int main()':
foo.cpp:4:1: error: types may not be defined in 'sizeof' expressions
foo.cpp:4:21: warning: statement has no effect [-Wunused-value]
Which says directly what’s wrong.
So it is a good idea to compile with different compilers.
Possibly you’re looking for compile time assertions.
With C++11 you can use static_assert, e.g. via a macro such as
#define STATIC_ASSERT( e ) static_assert( e, #e )
In C++03 you could implement it as a valid/invalid typedef, because a typedef can be repeated in the same translation unit, and can be used in a class definition:
#define STATIC_ASSERT( e ) typedef char staticAssert_shouldBeTrue[e? 1 : -1]
One problem with that was that g++ had/has a compiler bug, where a repeated typedef is not always accepted as it should be, necessitating generation of a locally unique name for each one, e.g. by using __LINE__.
But you can always just use the definition in the Boost library, since Boost supports most extant compilers with special-casing for each one as necessary.
First the macros BUILD_BUG_ON_ZERO and BUILD_BUG_ON_NULL trigger a compilation error if their argument is different than 0.
If the macro argument is 0, they will not trigger any compilation error but yield a 0 for BUILD_BUG_ON_ZERO and a (void *) 0 for BUILD_BUG_ON_NULL
These macros comes from the Linux kernel which is written in C and they are only working for C programs.
In C++ these macros are not working. The reason is in C++ you cannot declare a structure in a sizeof expression.
You don't mention in your question if you are compiling your program in C or in C++, but I strongly suspect you are compiling it in C++. So don't use these macros in C++.
Compiling with gcc -std=c99 -pedantic-errors, I get
screwed.c: In function ‘main’:
screwed.c:5:1: error: negative width in bit-field ‘<anonymous>’
screwed.c:5:1: error: struct has no named members [-pedantic]
and those are the errors the compilation should give when the code is compiled as C. The width of a bit-field must be non-negative (positive if it has a name), and a struct must have at least one named member (two, if the last one is a flexible array member). structs without tags are allowed.
You either compiled the code not as C, or your compiler is non-conforming.
When compiling as C++, the additional error
error: types may not be defined in ‘sizeof’ expressions
is generated (but the one about the struct without named members disappears).
In C++, you may not define type in a sizeof expression, and your compiler chose a less clear way of telling you.
Related
I'm getting the error "Expected '(' for function-style cast or type construction", and have done my best to research the meaning of this error online, but have been unable to find any documentation of what causes this error.
All the related questions on Stack Overflow that I have found bug fix a specific code snippet and do not explain more generally what is causing the error.
These include
Expected '(' for function-style cast or type construction answer highlights several issues with the code. Which issue is actually causing the error is unclear.
c++ Xcode expected '(' for function-style cast or type construction defines functions inside a main function. This seems like a clear syntax problem, but why this specific error is produced is still unclear to me.
'(' for function-style cast or construction type Xcode error. In this last example, the OP calls a function in a way that looks very similar to a function declaration, plus they declare a function with the same name but a different signature. Based on where the error is thrown and the message from the error, it seems that the error has something to do with function declarations.
Can I get a documentation-style answer that translates what "function-style cast" and "type construction" mean in simple english? When does the compiler choose to throw this error instead of some other error?
I don't want an answer that is specific to my own error, but as requested, here is my MCVE
#include <boost/integer_traits.hpp>
class Test{
const double MAX_DEPTH_VAL = (double) boost::integer_traits<unsigned short>.const_max;
const double MIN_DEPTH_VAL = (double) boost::integer_traits<unsigned short>.const_max;
};
I was led to believe that this syntax was possible, by this answer https://stackoverflow.com/a/2738576/3303546
This is a syntax error. Now, non-programmers or amateurs might hear the term syntax error and equate it with a general bug. But in C++ (and other languages) it has a more specific meaning.
There is a language grammar which is a set of rules by which the compiler, at an early stage of translation, breaks up the source code into logical groups. This is before any meaning is ascribed to those groups (that part is sometimes called semantic checking).
The syntax error you saw means that the compiler could not match up the source code to the grammar rules for C++. Precisely because it could not do this -- it's hard for the compiler to know what the programmer intended. So, syntax error messages are often guesses or don't relate to the programmer intention.
When you see this error, the compiler is suggesting a way of changing the code that would possibly match one of the grammar rules, but that may or may not actually be a good fix in the situation.
So, you can treat this sort of error just as "general syntax error", not worrying too much about the details of the error. To fix it, go back to simpler expressions that you are sure are not syntax errors, and then build up towards what you wanted to write.
An analogy for English language might be the sentence "I the room went of". Imagine some language translation software. This doesn't match any known sentence structure but what error message can it report? The actual suggestions probably won't help you to fix the sentence.
In your specific example, there is a syntax error. The g++ error message is different:
error: expected primary-expression before '.' token
where primary-expression is an entry in the C++ grammar. g++ sees the . token and assumes you mean the member access operator. But the grammar says that the left-hand operand of the member access operator must be a primary-expression (and the semantic rules say that this primary-expression denotes the object whose member you want to access).
However in your actual code the left-hand side is (double) boost::integer_traits<unsigned short> which does not match the grammar specification for primary-expression. (In fact it's a type name). The compiler can't proceed any further from here so it bails out.
Your compiler also failed to match the code to any grammar rule, but it guessed you were trying to write a function-style cast or type construction.
"Function-style cast" means code like int(5.0), so perhaps it recognized boost::integer_traits<unsigned short> as a type-name, and it guessed that you meant boost::integer_traits<unsigned short>(const_max), i.e. casting some variable const_max to that type.
I'm not sure what your compiler means by "type construction" here.
NB. If you want to know how to fix the actual code in your question, I'd suggest starting a new question where you post the code and error message and ask how to fix the code.
I fixed this error by adding -std=c++20 in my Makefile.
I have been trying to implement a method similar to static_assert which is defined in the C++11 standard. The main problem is how does the C++ compiler write the text message being passed to static_assert as a const char*? I can get the compiler to write a message like A_is_not_POD. This is what I have:
#define MY_STATIC_ASSERT(condition, name) \
typedef char name[(condition) ? 1 : -1];
But it would be quite nice to get the compiler to write something like "Error: A is not POD." Any suggestions?
Not sure i understand question, but C11 have _Static_assert(condition, errmessage). In C99 this functionality was missing but, depending on compiler, it could be possible to emulate. E.g. for gcc (unfortulately clang doesn't support attribute(error))
#define MY_STATIC_ASSERT(cnd, descr) ({ \
extern int __attribute__ ((error("static assert failed: (" #cnd ") (" #descr ")"))) \
compile_time_check(void); \
((cnd) ? 0 : compile_time_check()), 0; \
})
In the c99 standard there is no "official" way to perform a static assertion in your C++ compiler.
"The main problem is how does the C++ compiler write the text message being passed to static_assert as a const char*?"
The C++ compiler detects an error in the code and prints out an appropriate error message based on a standard list of messages it has for each error that is known it can encounter. In c99, the compiler doesn't know what a "static assert error" is, so you need to cause some other error.
However, because creating static asserts with a c99 compiler is kind of a hack, it is not capable of printing out a nice error message exactly how you want.
For your example,
#define MY_STATIC_ASSERT(condition, name) \
typedef char name[(condition) ? 1 : -1];
MY_STATIC_ASSERT(false, my_error_msg)
will trigger the "error: size of array ‘my_error_msg’ is negative" message in the gcc compiler (and should a similar message in other compilers, you hope!). Giving the array an error message for the name was a way to print out your own info. There are various other techniques/hacks you can do on purpose such as bad templates, enums link
Note: you can provide custom compiler messages prior to C++11 using pre-processor macros such as #error or #pragma. However pre-process time is not the same as compile-time! The the pre-processor has a limited ability to evaluate many expressions and keywords such as "if", "sizeof", "return" and so on have no meaning to the pre-processor, only the compiler. link with some overview
I've been looking through code golf and got an idea to try this code:
#define D #define after adding this line, everything worked fine, however I expanded it into this:
#define D #define
D VALUE
And here I got 5 compilation error. If I change D into #define everything is fine, can someone explain, why this code is illegal?
NOTE: I used VS2008 compiler.
EDIT: After some answers I see that I needed to give compilations error list:
error C2121: '#' : invalid character : possibly the result of a macro expansion
error C2146: syntax error : missing ';' before identifier 'VALUE'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2144: syntax error : 'void' should be preceded by ';'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
First error shows that D is not just define but also includes #.
C 2011 (N1570) 6.10.3.4 3: “The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one,…”
C++ 2010 (N3092) 16.3.4 [cpp.rescan] 3 has exactly the same text.
This code is illegal because language specification says it is illegal. According to C and C++ preprocessor specification, whatever code you build using preprocessor will never be interpreted as another preprocessor directive. In short, you cannot build preprocessor directives using preprocessor. Period.
(Also, you cannot build comments using preprocessor.)
It does look like your preprocessor is making the substitution you want, but you likely wouldn't get the behaviour you want - the preprocessor is normally just a single pass operation. Example (with clang, but you should be able to reproduce by using the appropriate VS2008 flags):
$ cat example.c
#define D #define
D VALUE
$ cc -P -E example.c
#define VALUE
That #define VALUE is going straight through to the compiler, which won't know what to do with it - it's a preprocessor directive, after all. Clang's error, for reference, is similar to yours:
$ cc -c example.c
example.c:2:1: error: expected identifier or '('
D VALUE
^
example.c:1:11: note: expanded from macro 'D'
#define D #define
^
1 error generated.
That won't work because preprocessing is performed in a single pass. For example, consider the next code :
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
int main() {
return 0;
}
After preprocessing, your code will looks like :
#define N 6
int main() {
return 0;
}
and "#define" is not a valid syntax on C or C++. Also, since the resulting preprocessor directive is not going to be processed, it won't resolve subsequent references to the "N" macro in your code.
Just for fun, you can call the preprocesor twice from the command line using g++/gcc. Consider the next code (define.cpp) :
#include <iostream>
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
using namespace std;
int main() {
cout << N << endl;
return 0;
}
Then you can do:
$ g++ -E define.cpp | g++ -o define -x c++ - && ./define
and will output:
6
Lines of code in the pre-processors eyes are either pre-processor statements (And thus don't have any replacements done on them) or normal text statements (And have replacements done). You can't have one be both, so once you have 'D' be replaced it's only going to look to see if there are any more macros to replace. Since there are none, it just leaves '#define' in the C++ code as it is and then the C++ compiler will error when it sees it (Since '#define' isn't valid C++ code).
So show my point more, this is invalid code for the pre-processor:
#define D define
#D value
Because the pre-processor doesn't do any macro replacement on pre-processor statements, and "#D" isn't a recognized pre-processor command. And this:
#define D #define
D value
Results in this C++ code:
#define value
Which is invalid because the pre-processor is already done being run.
Looking at the grammar in 16 [cpp] paragraph 1, a replacement-list consists of pp-tokens which may include the production # no-directive which is described in paragraph 2 of the same paragraph as
A non-directive shall not begin with any of the directive names appearing in the list.
That is, something of the form
#define NAME # define
happens to be illegal! Also note that the # in this context does not turn the next word into a string: the quoting following a # only happens shen the # is immediately followed by a macro parameter name in a function-style macro.
This question popped into my head today at work when I was having yet another domestic affair with my compiler. Despite my buff pinky (due to all the semicolon pressing I do at work), I managed to miss one before an if statement. Obviously, this resulted in a compile error:
error C2143: syntax error : missing ';' before 'if'
So I wondered "well gee, why can't you tell me the line that's missing the semicolon instead of the line after the problem." and I proceeded to experiment with other similar syntax errors:
error C2065: 'myUndeclared' : undeclared identifier
error C2143: syntax error : missing ')' before 'if'
etc...
Now, all of those errors would, similarly, take me to the line after the problem and complain about something before the if statement.
Consider the following:
SomeFunction(x) //Notice, there is no ';' here
if(bSomeCondition)
{
...
}
I get two compile errors:
(Line 265) error C2065: 'x' : undeclared identifier
(Line 266) error C2143: syntax error : missing ';' before 'if'
However, the first error correctly tells me the line number, despite the missing semicolon. This suggests to me that the compiler doesn't get tripped up in parsing and is able to make it past the semicolon problem. So, why is it that the compiler insists on grammatical errors being reported in this way? Other errors (non grammatical) are reported on the lines they are found. Does this have to do with the compiler making multiple passes? Basically, I hope someone with a working knowledge of the C++ compiler might explain specifically what the compiler is doing that necessitates the reporting of errors in this "before" way.
The short answer to the more general question of "Why do C/C++ error messages suck" is "Sometimes C++ is really hard to parse" (it doesn't actually have a context free grammar). However, this isn't really a valid reason - one can still make tools that record better diagnostic information than most C++ compilers.
The more practical answer is "Compiler authors have inherited legacy codebases which didn't value error messages", combined with a mild dose of "compiler authors are lazy", topped with "Diagnostic reporting isn't an exciting problem". Most compiler writers would add a new language feature or 3% codegen performance improvement, rather than do significant refactoring on the codebase to allow decent error reporting. The specific question about "Why aren't errors properly localised to the line that 'caused' them" is an instance of this. There's not really a technical reason compilers can't generally work out that a ; is missing
, and then tell you about the source span of the last ; lacking statement - even in the presence of C++'s general whitespace invariance. It's just that storing that information has (largely) been historically ignored.
That said, new compilers not hampered by decades of old code are doing much better. Have a look at the Clang compiler, which prides itself on sensible error messages. The page on diagnostics shows how much better than GCC they are. An example for this case being:
$ gcc-4.2 t.c
t.c: In function 'foo':
t.c:5: error: expected ';' before '}' token
$ clang t.c
t.c:4:8: error: expected ';' after expression
bar()
^
;
Or, more impressively:
$ cat t.cc
template<class T>
class a {}
class temp {};
a<temp> b;
struct b {
}
$ gcc-4.2 t.cc
t.cc:3: error: multiple types in one declaration
t.cc:4: error: non-template type 'a' used as a template
t.cc:4: error: invalid type in declaration before ';' token
t.cc:6: error: expected unqualified-id at end of input
$ clang t.cc
t.cc:2:11: error: expected ';' after class
class a {}
^
;
t.cc:6:2: error: expected ';' after struct
}
^
;
Look, it's even telling us what to type where to fix the problem! </clang_salespitch>
Because in C++, white-space doesn't matter, on the whole. So this is valid code:
SomeFunction(x)
;if(bSomeCondition)
{
...
}
So the compiler message is simply reporting that a semi-colon hasn't appeared somewhere before the if.
In this code:
SomeFunction(x)
if (y) {
}
As you said, the error would be reported on line 2 as missing ';' before 'if'.
There is not wrong with line 1. It's perfectly valid without a semi-colon, and several expressions are possible besides just a semi-colon (such as a dot, or a math operator, or assignment, or a pointer, etc).
So, reporting the error on the previous line may not always make sense, take this example:
SomeFunction(x)
+= 10
- 5
// blank line
// blank line
if (y) {
}
Which line has the error? The line with the - 5? Or one of the comment lines? To the compiler, the error is actually with the 'if', since it is the first place that something can be detected as being wrong. To report a different line, the compiler would have to report the last properly parsed token as the error, rather than the first place the error is detected. That sounds a little backwards, and saying that //blank line1 is missing a semi-colon is even more confusing, since changing it to //blank line; would of course not change or fix the error.
By the way, this is not unique to C or C++. This is a common way to report errors in most parsers.
Quite simply, because of how parsing is done. When the parser expects ;, and instead encounters if, the error is in the if. The simplest sane way to report it is to say ; was expected before if.
The compiler is white space agnostic. It doesn't know (or care) that there is a carriage return or tabs or spaces in between your statements. all it cares about is what is after or before semi colons, or after/before brackets ('{','}') which end and begin classes and functions. That's why :)
Because when it's done parsing that line it does not know that you wanted a semicolon there yet. Let's look at an example:
int mystuff
Is this line missing a semicolon? That depends on what comes next. For instance the following construct is perfectly ok:
int mystuff
= 1;
I would never write it like that, but for the compiler it is ok.
Because, the following code would be correct:
SomeFunction(x)
;if(bSomeCondition)
{
}
That's because unecessary whitespaces are ignored.
The short answer: you can put ; into line 266, and then it's going to be fine. From the compiler's perspective the error is there.
You might want to try clang, although I don't know whether it gives better error message for this particular type of error but in general it gives a lot clearer error messages.
It is because compiler checks for 1 whole statement. Let me give an example:
int a,b,c
c=a+b;
cout<<c;
This code generates compilation error, that "; is expected before c/line 2", this happens because compiler first looks at line 1's int a,b,c and the compiler has no clue whether there will be any other variable or statement and so the compiler moves to second line(because whitespaces are allowed), and then it sees that there is "c=a+b", which is a statement, and thus compiler knows that something is wrong, as it was expecting either a variable or a semicolon(;). And so, it tells us that it was expecting a ; before a statement.
So long story short, compiler doesn't look for a semicolon after a statement(if that was the case we might not be able to use whitespaces in our codes), it looks for ; right before the other statement, because compiler has no clue how long the first statement would be.
Considering this answer for the benefit of typedefs on basic types and why they are used, is there any way to ensure that in your project you did not use a basic type and used the typedef counterparts?
If you really, absolutely want to ban native types but allow typedefs, I guess you can always do something like:
#include <stdint.h>
#define int please_use_stdint_typedefs_rather_than_native_types
int main()
{
int32_t good; // Good typedef.
int evil; // Evil native type.
}
$ gcc -c int_forbidden.c
int_forbidden.c: In function ‘main’:
int_forbidden.c:8: error: ‘please_use_stdint_typedefs_rather_than_native_types’ undeclared (first use in this function)
int_forbidden.c:8: error: (Each undeclared identifier is reported only once
int_forbidden.c:8: error: for each function it appears in.)
int_forbidden.c:8: error: expected ‘;’ before ‘evil’
That said, I don't think outright banning native types is a good idea in the general case.
You can make these typedefs Strong Typedefs as proposed in this boost library : http://www.boost.org/doc/libs/1_40_0/boost/strong_typedef.hpp
Considering a typedef is just a synonym for a type and does not actually create a new type, I don't think there would be any reliable way to ensure this. You could write a script to run through the code and look for occurrences of primitive types vs. the expected typedef counterpart.