Warning # | Warning description |
---|---|
too many arguments in function call | |
a value of type "type" cannot be used to initialize an entity of type "type" | |
declaration is incompatible with "entity" (declared at line xxxx) | |
unrecognized #pragma | |
argument of type "type" is incompatible with parameter of type "type" | |
function "xxxx" declared implicitly | |
a value of type "type" cannot be assigned to an entity of type "type" | |
byte order must be 'littleendian', 'bigendian', 'default', or 'default_header' | |
byte order stack is empty, pop ignored | |
implicit pointer conversion changes byte order | |
pointer conversion changes byte order | |
adjacent bit fields have different byte order | |
byte order attributes are not supported here | |
byte order mismatch in format string conversion | |
byte order is incompatible with entity-kind "entity" (declared at line xxxx) | |
OpenMP* for-init variable should be little-endian | |
extern prefix does not match previous declaration | |
implicit pointer conversion (involving void) changes byte order | |
pointer conversion (involving void) changes byte order | |
argument of type "type" is incompatible with parameter of type "type" (dropping qualifiers) | |
a value of type "type" cannot be used to initialize an entity of type "type" (dropping qualifiers) | |
a value of type "type" cannot be assigned to an entity of type "type" (dropping qualifiers) | |
possible byte order mismatch passing va_list | |
function pointer conversion from "xxxx" to "xxxx" changes byte order | |
byte order mismatch in reference initialization | |
field has a different byte order than the preceding field | |
OpenMP atomic expression should be little-endian | |
variable in OpenMP reduction clause should be little-endian | |
function "xxxx" has no prototype (byte order of pointed-to type may not be verified) | |
calling "xxxx" through function pointer "yyyy" has undefined behavior | |
invalid conversion from function pointer type "xxxx" to type "yyyy": prototype-less functions obey stricter rules during invocation | |
Byte order of variable "xxxx" was changed to little-endian/big-endian to resolve mismatch during pointer conversion |
140: too many arguments in function call
Diagnostic is enabled by default.
Compile the test case below with icc -c t140.c
:
int foo(int x) { return 0; } int foo2(int x) { return foo(1,2); }
Compilation output is as follows:
t140.c(4): error #140: too many arguments in function call return foo(1,2); ^
Explanation and resolution:
The function, foo
, is being called with two arguments whereas the function definition specifies one parameter. To resolve this issue, ensure the number of arguments passed in each call to a function agrees with the number of parameters specified in the function declaration/definition. In this example, either modify the call to foo
so the number of arguments passed agrees with the definition or modify the definition and all of the other calls of foo
so the number of parameters and arguments agree.
144: a value of type "type" cannot be used to initialize an entity of type "type"
Diagnostic is enabled by default.
Compile the test case below with icc -little-endian -c t144.c
:
struct foo { __attribute__((bigendian)) int x; }; struct foo2 { __attribute__((bigendian)) int x; }; int foo() { struct foo z; z.x = 5; struct foo2 y = z; return 0; }
Compilation output is as follows:
t144.c(13): error: a value of type "struct foo" cannot be used to initialize an entity of type "struct foo2" struct foo2 y = z; ^
Explanation and resolution:
An aggregate of one type cannot be used to initialize an aggregate of another type, even if the individual components agree in terms of size and type. In the example above, struct foo
and struct foo2
are similar in terms of their underlying fields, yet an error is still flagged.
To resolve, create a routine that copies the individual components of one aggregate to the other and employ this routine to initialize the struct.
147: declaration is incompatible with entity-kind "entity" (declared at line xxxx)
Diagnostic is enabled by default
Compile the test case below with icc -c t147.c:
void func(int a); void func(unsigned int a) { }
Compilation output is as follows:
t147.c(3): warning #147: declaration is incompatible with "void func(int)" (declared at line 1) void func(unsigned int a) { ^
Explanation and resolution:
In this example, the parameter specified on the function declaration does not precisely match the parameter specified on the function definition. The compiler flags a diagnostic because there is a risk of the definition interpreting arguments passed to it differently than what the programmer is expecting when viewing the declaration.
To resolve, ensure the parameters precisely match between function declarations and definitions.
161: unrecognized #pragma
Diagnostic is enabled by default.
Compile the test case below with icc -c t161.c
:
#pragma byte_order(littleendian) int x;
Compilation output is as follows:
t161.c(1): warning #161: unrecognized #pragma #pragma byte_order(littleendian) ^
Explanation and resolution:
The bi-endian features are not turned on by default. To turn on, you must specify either the -little-endian or -big-endian option.
167: argument of type "type" is incompatible with parameter of type "type"
Diagnostic is enabled by default.
Compile the test case below with icc -c -big-endian t167.c:
static char *bar (int *a) { a++; return "bar"; } static void foo2 (char *a) { unsigned char *data; data = bar(a); }
Compilation output is as follows:
t167.c(10): warning #167: argument of type "char *" is incompatible with parameter of type "int *" data = bar(a);
Explanation and resolution:
The argument, a
, cannot be assumed to safely convert to the type expected by the function, bar
, without a potential loss of data. In the context where the callee and caller have the same byte order, it may be safe to assume that the pointer, char *
, points to the low order byte of an integer. In the context of the bi-endian compiler, this implicit type change may result in individual bits being in unexpected locations by the called function. If the argument is of a different byte order than what is specified by the parameter of the function definition, the individual bytes that comprise an integer may be in different locations of the integer and result in incorrect results.
A safe fix is to introduce a temporary with the same byte order as the called function, initialize the temporary with the value, and pass a reference to it. The following code uses this technique to address the issue in the previous example:
static char *bar (int *a) { a++; return "bar"; } static void foo2 (char *a) { unsigned char *data; int x = (int)*a; data = bar(&x); }
266: function "xxxx" declared implicitly
Diagnostic is enabled by default.
Compile the test case below with icc -big-endian -c t266.c
:
int foo(int x) { zee(x); return 0; }
Compilation output is as follows:
t266.c(2): warning #266: function "zee" declared implicitly zee(x); ^
Explanation and resolution:
With the bi-endian compiler, implicit assumptions about the parameters to a function are problematic. The bi-endian compiler may adjust byte order of the argument so the parameter passed to a method is compatible with the expected argument (for example, passing a little-endian integer to a function that expects a big-endian integer). If the compiler does not know the prototype of the called function, there is a large risk of passing a value using incorrect byte order.
To fix this issue, ensure all of your functions have prototypes visible in the compilation unit where the function is called.
556: a value of type "type" cannot be assigned to an entity of type "type"
Diagnostic is enabled by default.
Compile the test case below with icc -c -big-endian t556.c
:
static int *bar (int *a) { a++; return a; } static void foo2 (char *a) { unsigned char *data; data = bar((int *)a); }
Compilation output is as follows:
t556.c(10): warning #556: a value of type "int *" cannot be assigned to an entity of type "unsigned char *" data = bar((int *)a);
Explanation and resolution:
The assignment to the variable data cannot be assumed to safely convert to the new type without potential loss of information. In the context of the bi-endian compiler, this implicit type change may result in individual bits being in unexpected locations. Specifically, the least significant byte that comprises an integer is not in the same location between an integer with big-endian byte order and an integer with little-endian byte order.
A safe fix is for the programmer to inspect the code and write a conversion routine that correctly assigns the correct component especially if a byte order boundary is being crossed.
1694: byte order must be 'littleendian', 'bigendian', 'default', or 'default_header'
Diagnostic is enabled by default.
Compile the test case below with icc -big-endian -c t1694.c
:
#pragma byte_order(little-endian) int x;
Compilation output is as follows:
t1694.c(1): error: byte order must be 'littleendian', 'bigendian', 'default', or 'default_header' #pragma byte_order(little-endian)
Explanation and resolution:
Spelling of the arguments to the various pragmas and attributes must be correct. In this example, it can be confusing because the compiler option to enable the bi-endian feature is -little-endian or -big-endian. Ensure you spell the arguments to the bi-endian attributes and pragmas correctly.
1695: byte order stack is empty, pop ignored
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian -DERR t1695.c
:
#pragma byte_order (push, littleendian) #pragma byte_order (pop) #ifdef ERR #pragma byte_order (pop) #endif
Compilation output is as follows:
t1695.c(5): warning #1695: byte order stack is empty, pop ignored #pragma byte_order (pop) ^
Explanation and resolution:
The byte_order and extern_prefix pragmas allow pushing and popping of state, operating with stack-like behavior. If the stack is empty and a pop appears in the compilation unit, you will receive this warning. Ensure the use of push and pops are balanced such that at the end of compilation, the byte_order and extern_prefix stacks are either one or empty in depth.
1696: implicit pointer conversion changes byte order of the pointed-to types from "xxxx" to "xxxx"
Diagnostic is enabled by default.
Compile the test case below with icc -little-endian -c t1696.c
:
#pragma byte_order (push, bigendian) int *z; #pragma byte_order (pop) int foo(int *x) { z = x; return 0; }
Compilation output is as follows:
t1696.c(6): warning #1696: implicit pointer conversion changes byte order of the pointed-to types from "int (related declaration at t1696.c(5))" to "bigendian int (related declaration at t1696.c(2))" z = x; ^
Explanation and resolution:
The problem is that the underlying pointed to type (in the example x
is a pointer to a little-endian integer) has a different byte order than what is expected in the assignment (z
points to a big-endian integer). Therefore, dereferencing of the assigned pointer (z
) may result in reading the value in the opposite byte order as was intended and thus incorrectly.
The primary technique to address the issue is to create a global or static with the same byte order as the pointed to type of the left hand side of the assignment. In the example above this can be accomplished creating a static variable, z_tmp
, which matches the pointed to type of z
. The explicit assignments are done with *x
assigned to z_tmp
and the address of z_tmp
assigned to z
which enables the compiler to insert byte swap operations where necessary. The following code uses this technique to address the issue:
#pragma byte_order (push, bigendian) int *z; #pragma byte_order (pop) int foo(int *x) { static int z_tmp __attribute__((bigendian)); z_tmp = *x; z = &z_tmp return 0; }
1697: pointer conversion changes byte order of the pointed-to types from "xxxx" to "xxxx"
Diagnostic is disabled by default.
Compile the test case below with icc -c -no-swap-pointers -little-endian t1697.c
:
#pragma byte_order (push, bigendian) #pragma warning (error: 1697) typedef int mybeint; mybeint datum = 0; void get(mybeint *be) { *be = datum; } void func() { mybeint y = 5; mybeint *ptrY = &y; get((mybeint*)&ptrY); } #pragma byte_order (pop)
Compilation output is as follows:
t1697.c(14): error: pointer conversion changes byte order of the pointed-to types from "mybeint * (related declaration at t1697.c(13))" to "mybeint (related declaration at t1697.c(4))" get((mybeint*)&ptrY); ^
Explanation and resolution:
The issue is the underlying pointed to type between the original and converted value differ in byte order. This example uses the -no-swap-pointer option which makes all pointers have little-endian byte order.
In the specific example, &ptrY
is a little-endian pointer to a little-endian pointer to a big-endian integer. It is being cast to a little-endian pointer to a big-endian integer effectively stripping away one pointer deference and treating the second level little-endian pointer as a big-endian integer, and thus a diagnostic is flagged.
The resolution is to cast the second level little-endian pointer to a little-endian integer and then assign it to a big-endian integer whose address is then passed. The key is to explicitly communicate the transition from little-endian to big-endian by assignment which allows the compiler to convert the underlying pointer type, in this case z1
, to big-endian, before passing a reference to it.
The following code uses this technique to address the issue:
#pragma byte_order (push, bigendian) #pragma warning (error: 1697) typedef int mybeint; typedef __attribute__((littleendian)) int myleint; mybeint datum = 0; void get(mybeint *be) { *be = datum; } void func() { mybeint y = 5; mybeint *ptrY = &y; myleint z1; mybeint z2; z1 = (myleint)ptrY; z2 = z1; get((mybeint*)&z2); ptrY = (mybeint*)z2; } #pragma byte_order (pop)
1700: adjacent bit fields have different byte order
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian t1700.c
:
typedef __attribute__((bigendian)) int be_int; typedef __attribute__((littleendian)) int le_int; struct foo { be_int x:16; le_int y:16; };
Compilation output is as follows:
t1700.c(6): error #1700: adjacent bit fields have different byte order le_int y:16; ^
Explanation and resolution:
The big-endian and little-endian bit fields are allocated differently in their containers. Big-endian bit fields are allocated from high to low bit, while little-endian bit fields are allocated from low to high bit. As a result, big-endian and little-endian bit fields allocated to the same container could potentially overwrite each other. Therefore, the compiler issues an error when it detects a struct contains both big-endian and little-endian bit fields.
The fix is to ensure all bit fields contained in the struct agree on byte order.
1706: byte order attributes are not supported here
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian t1706.c
:
struct foo __attribute__((littleendian)) { int a; int b; }; __attribute__((littleendian)) struct foo{ int a; int b; };
Compilation output is as follows:
t1706.c(1): error #1706: byte order attributes are not supported here struct foo __attribute__((littleendian)) { ^ t1706.c(1): error: expected an identifier struct foo __attribute__((littleendian)) { ^ t1706.c(1): error: expected a ";" struct foo __attribute__((littleendian)) { ^ t1706.c(4): warning #12: parsing restarts here after previous syntax error }; ^ t1706.c(6): error #1706: byte order attributes are not supported here __attribute__((littleendian)) struct foo{ ^
Explanation and resolution:
Placement of byte order attributes follows the GNU protocol. See http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html#Type-Attributes.
1872: byte order mismatch in format string conversion
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian t1872.c
:
#include <stdio.h> #pragma byte_order(push,bigendian) int tempval; #pragma byte_order(pop) int foo() { scanf("%d", &tempval); return 0; }
Compilation output is as follows:
t1872.c(7): warning #1872: byte order mismatch in format string conversion scanf("%d", &tempval); ^
Explanation and resolution:
The problem is that a reference (in the example, &tempval
) is being passed to a function where the underlying pointed to type is in the opposite byte order that the function expects. In the example, scanf expects a pointer to a little-endian integer and assigns a value to it in little-endian byte order. Upon return, the value would be interpreted as having big-endian byte order and read incorrectly.
The fix for this problem is to create a temporary of the correct byte order and pass a reference to it to the function. After the function, assign the value of the temporary to the original variable.
A solution for the example code appears as follows:
#include <stdio.h> #pragma byte_order(push,bigendian) int tempval; #pragma byte_order(pop) int foo() { int x ; scanf("%d", &x); tempval = x ; return 0; }
1873: byte order is incompatible with "entity" (declared at line xxxx)
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian t1873.c
:
#define __le __attribute__((littleendian)) #define __be __attribute__((bigendian)) #pragma warning (error: 1873) void func_need_warns(int __be a); void func_need_warns(int __le a) { } int main(int argc, char ** argv) { int b = 10; func_need_warns(b); return 0; }
Compilation output is as follows:
t1873.c(8): error: byte order is incompatible with "void func_need_warns(int)" (declared at line 6) void func_need_warns(int __le a) { } ^
Explanation and resolution:
Note: The test case uses #pragma warning to turn the diagnostic, which by default is a warning, into an error.
The problem is that the byte order of a parameter between a declaration and definition of the same function differs.
The resolution is to ensure declarations and definitions match with regard to the byte order of their parameters.
1927: OpenMP* for-init variable should be little-endian
Diagnostic is enabled by default.
Compile the test case below with icc -big-endian -openmp -c t1927.c :
void foo() { int i; #pragma omp parallel for for (i = 0; i < 100; i++) { } }
Compilation output is as follows:
t1927.c(4): error: Open MP for-init variable should be little-endian for (i = 0; i < 100; i++) { ^
Explanation and resolution:
Current implementation obligates OpenMP for-init variable to have little-endian byte order.
The recommended way of correcting the above error is to explicitly set the byte order of the OpenMP for-init variable to little-endian using __attribute__((littleendian)) in the place of the definition. The following code uses this technique to address the issue:
void foo() { int __attribute__((littleendian)) i; #pragma omp parallel for for (i = 0; i < 100; i++) { } }
2202: extern prefix does not match previous declaration
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian t2202.c
:
#pragma extern_prefix("") int dec(int i); #pragma extern_prefix("__be_") int dec(int i) { return --i; }
Compilation output is as follows:
t2202.c(4): error #2202: extern prefix does not match previous declaration int dec(int i) ^
Explanation and resolution:
The problem is that there is a declaration and definition of a function where the active extern_prefix does not match. Pragma extern_prefix is intended to allow a big-endian and little-endian version of functions with the same declared name in different compilation units by enabling the names used at link time to be different. Pragma extern_prefix is not intended to allow this capability in the same compilation unit as attempted with the example. Most likely, the developer does not intend to have two functions with the same declared name and different byte orders in the same translation unit. The fix is to make sure the active extern_prefix matches between declaration and definition. If the intention is to have two different functions in the same compilation unit, the functions must have two different names in the source code.
The preprocessor, in combination with #pragma macro_push and #pragma macro_pop can be used to re-define a name according to the implicit default byte order of a file. This mechanism can be used such that a single name can actually reference two different functions according to that implicit default byte order.
2324: implicit pointer conversion (involving void) may change byte order of the pointed to types from "xxxx" to "xxxx"
Diagnostic is disabled by default.
Compile the test case below with icc -little-endian -c t2324.c
:
#pragma byte_order (push, littleendian) #pragma warning (error : 2324 2325) typedef int myleint; typedef void void_le; void func(myleint *arg); #pragma byte_order (pop) #pragma byte_order (push, bigendian) void *void_var1; #pragma byte_order(pop) int main() { func(void_var1); return 0; }
Compilation output is as follows:
t2324.c(13): error: implicit pointer conversion (involving void) may change byte order of the pointed-to types from "bigendian void (related declaration at t2324.c(9))" to "myleint (related declaration at t2324.c(5))" func(void_var1); ^
Explanation and resolution:
The issue is a void * defined in a big-endian context is passed to a function that expects a pointer to a little-endian integer. The risk is that the void * may point to a value that is big-endian and thus a diagnostic is flagged.
If upon inspection, the programmer determines that the void * does indeed point to a value that has the opposite byte order, the programmer can address similar to the solution for diagnostic #1696.
If upon inspection, the programmer determines there is no real issue, the diagnostic can be silenced by adding a cast as follows:
func((void_le*)void_var1);
There will not be a diagnostic for casting from a pointer to a void of one byte order to a pointer to a void of the other byte order.
In some cases, the best way to address this diagnostic is to employ two different functions, one for the big endian code to call and another for the little-endian code to call, each with a pointer to a void of the corresponding byte order.
2325: pointer conversion (involving void) may change byte order of the pointed to types from "xxxx" to "xxxx"
Diagnostic is disabled by default.
Compile the test case below with icc -little-endian -c t2325.c
:
#pragma byte_order (push, littleendian) #pragma warning (error : 2324 2325) typedef int myleint; typedef void void_le; void func(myleint *arg); #pragma byte_order (pop) #pragma byte_order (push, bigendian) typedef int mybeint; mybeint be; #pragma byte_order(pop) int main() { func((void_le *)&be); return 0; }
Compilation output is as follows:
t2325.c(14): error: pointer conversion (involving void) may change byte order of the pointed-to types from "mybeint (related declaration at t2325.c(10))" to "void_le (related declaration at t2325.c(4))" func((void_le *)&be); ^
Explanation and resolution:
The issue is a pointer to a big-endian integer is cast to a void * defined in the context of a default little-endian byte order. The risk is that the void * may be intended to be used as a value with little-endian byte order. Thus a diagnostic is flagged so the programmer can check his/her assertions.
If upon inspection, the programmer determines that the void * does indeed point to a value that has the opposite byte order, the programmer can address similar to the solution for diagnostic #1697. A second technique is to create two versions of function, one explicitly designed to handle little-endian values, and the other designed to handle big-endian values.
If upon inspection, the programmer determines there is no real issue, the diagnostic can be silenced by adding a cast as follows:
func((void_le*)(void_be *)&be);
2330: argument of type "type" is incompatible with parameter of type "type" (dropping qualifiers)
Diagnostic is enabled by default.
Compile the test case below with icc -little-endian -c t2330.c
:
int debug_func(char *file, char *description, int line) { return 0; } int main () { debug_func("abc", __FUNCTION__, 10); return 0; }
Compilation output is as follows:
t2330.c(9): warning #2330: argument of type "const char *" is incompatible with parameter of type "char *" (dropping qualifiers) debug_func("abc", __FUNCTION__, 10); ^
Explanation and resolution:
The issue is that the const qualifier is lost as the called function, debug_func, declares the parameter description as only char *. There is the risk that the function, debug_func, will modify the value pointed to by description, thus using the argument in an unintended fashion.
The resolution is to ensure that parameters and arguments match in terms of qualifiers. This diagnostic is distinct from #167 so that it can be separately disabled if it is decided not to address the qualifier incompatibility.
2331: a value of type "type" cannot be used to initialize an entity of type "type" (dropping qualifiers)
Diagnostic is enabled by default.
Compile the test case below with icc -little-endian -c t2331.c
:
int main () { char *cp = __FUNCTION__; return 0; }
Compilation output is as follows:
t2331.c(4): warning #2331: a value of type "const char *" cannot be used to initialize an entity of type "char *" (dropping qualifiers) char *cp = __FUNCTION__; ^
Explanation and resolution:
The issue is that the const qualifier is lost as the left hand side of the assignment, cp
is declared as only char *. There is the risk that cp
will be used in contexts that modify the value pointed to by it, thus using the value in an unintended fashion.
The resolution is to inspect these types of assignments and ensure that the types match in terms of qualifiers. This diagnostic is distinct from #144 so that it can be separately disabled if it is decided not to address the qualifier incompatibility.
2332: a value of type "type" cannot be assigned to an entity of type "type" (dropping qualifiers)
Diagnostic is enabled by default.
Compile the test case below with icc -little-endian -c t2332.c
:
int main () { char *cp1; cp1 = __FUNCTION__; return 0; }
Compilation output is as follows:
t2332.c(5): warning #2332: a value of type "const char *" cannot be assigned to an entity of type "char *" (dropping qualifiers) cp1 = __FUNCTION__; ^
Explanation and resolution:
The issue is that the const qualifier is lost as the left hand side of the assignment, cp1
is declared as only char *. There is the risk that cp1
will be used in contexts that modify the value pointed to by it, thus using the value in an unintended fashion.
The resolution is to inspect these types of assignments and ensure that the types match in terms of qualifiers. This diagnostic is distinct from #556 so that it can be separately disabled if it is decided not to address the qualifier incompatibility.
2333: possible byte order mismatch passing va_list
Diagnostic is enabled by default.
Compile the test case below with icc -little-endian -c t2333.c
:
#include <stdio.h> #include <stdarg.h> #pragma byte_order (push, bigendian) #pragma warning(error: 2333) void invmgr_dbg(const char *format, ...) { va_list args; va_start(args, format); va_end(args); vprintf(format, args); } int main() { int abc = 1234; invmgr_dbg(" %d %d %d 0x%x\n", 1, 2, abc, &abc); return 0; } #pragma byte_order (pop)
Compilation output is as follows:
t2333.c(11): error: possible byte order mismatch passing va_list vprintf(format, args); ^
Explanation and resolution:
Note: pragma warning is used in the test case to turn the diagnostic, which by default is a warning, into an error.
The issue is that the args variable of type va_list contains arguments that are declared in big-endian byte order while the vprintf function expects arguments in little-endian byte order.
To address this issue, declare the function (in this example invmgr_dbg()) in the context of a little-endian default byte order.
2334: function pointer conversion from "xxxx" to "xxxx" changes byte order
Diagnostic is disabled by default.
Compile the test case below with icc -big-endian -c -diag-enable 2334 t2334.c:
void foo(int __attribute__((littleendian)) i) {} typedef void (* foo_t)(int i); foo_t ptr = (foo_t)&foo
Compilation output is as follows:
t2334.c(3): warning #2334: function pointer conversion from "bigendian void (*bigendian)(int) (related declaration at t2334.c(1))" to "foo_t (related declaration at t2334.c(2))" changes byte order foo_t ptr = (foo_t)&foo; ^
Explanation and resolution:
Note: -diag-enable 2334 command line option is used to enable the diagnostic.
The problem is that the byte order of a formal parameter (in this example parameter "i"
) is changed as a result of explicit cast operation of a function pointer. The formal parameter "i"
is explicitly defined as a little-endian integer but "(foo_t)&foo"
casts it to a big-endian integer.
The solution is to ensure that parameters' byte order is not changed as a result of explicit function pointer conversion unless it is intentional.
2608: byte order mismatch in reference initialization
Diagnostic is enabled by default.
Compile the test case below with icpc -big-endian -c t2608.c:
int __attribute__((littleendian)) z; void foo() { int &x = z; }
Compilation output is as follows:
t2608.c(3): warning #2608: byte order mismatch in reference initialization int &x = z; ^
Explanation and resolution:
The reasons and solution of this warning are exactly the same as for warning #1696 with one exception. This warning is C++ specific and used to diagnose byte order mismatch problems during reference initialization.
2710: field has a different byte order than the preceding field
Diagnostic is disabled by default.
Compile the test case below with icc -big-endian -c -diag-warning 2710 t2710.c
:
#include <stddef.h> struct S { int i; size_t j; };
Compilation output is as follows:
t2710.c(4): warning #2710: field has a different byte order than the preceding field size_t j; ^
Explanation and resolution:
Some structures might use types from 3rd party header files, which would cause the structure to have fields of different byte order. That could be unexpected and overlooked. Remark #2710 can be used as a hint to identify possible byte order related issues.
2940: OpenMP atomic expression should be little-endian
Diagnostic is enabled by default.
Compile the test case below with icc -big-endian -openmp -c t2940.c
:
void foo() { int x; int __attribute__((littleendian)) i; #pragma omp parallel for for (i = 0; i < 100; i++) { #pragma omp atomic x++; } }
Compilation output is as follows:
t2940.c(7): warning #2940: OpenMP atomic expression should be little-endian x++; ^
Explanation and resolution:
Current implementation uses critical sections to perform atomic operations with big-endian data. This could result in performance losses comparing to native support for atomic operations. You may consider using little-endian byte order for atomically updated variable to get the best performance:
void foo() { int __attribute__((littleendian)) x; int __attribute__((littleendian)) i; #pragma omp parallel for for (i = 0; i < 100; i++) { #pragma omp atomic x++; } }
2941: variable in OpenMP reduction clause should be little-endian
Diagnostic is enabled by default.
Compile the test case below with icc -big-endian -openmp -c t2941.c
:
void foo() { int sum = 0; int __attribute__((littleendian)) i; #pragma omp parallel for reduction(+:sum) for (i = 0; i < 100; i++) { sum += 1; } }
Compilation output is as follows:
t2941.c(4): error: variable in OpenMP reduction clause should be little-endian #pragma omp parallel for reduction(+:sum) ^
Explanation and resolution:
Current implementation does not support reduction operations with big-endian data. The recommended way of correcting the above error is to explicitly set the byte order of the Open MP reduction variable to little-endian using __attribute__((littleendian)) in the place of the definition.
The following code uses this technique to address the issue:
void foo() { int __attribute__((littleendian)) sum = 0; int __attribute__((littleendian)) i; #pragma omp parallel for reduction(+:sum) for (i = 0; i < 100; i++) { sum += 1; } }
2942: function "xxxx" has no prototype (byte order of pointed-to type may not be verified)
Diagnostic is enabled under -param-byte-order=little-endian only.
Compile the test case below with icc -big-endian -param-byte-order=little-endian -c t2942.c :
int foo(int *x) { zee(x); return 0; }
Compilation output is as follows:
t2942.c(2): warning #2942: function "zee" has no prototype (byte order of pointed-to type may not be verified) zee(x); ^
Explanation and resolution:
To ensure that parameters are passed in the same byte order as they are received, a function prototype should be seen at a call site. When -param-byte-order=little-endian command line option is used, all parameters are passed and received in little-endian byte order regardless of prototype availability. That is why warning #266 is not relevant and suppressed by the compiler. Byte orders of the parameters' pointed-to types may still mismatch. Thus if an argument with a pointer type is used to make a call and the prototype is not available, the compiler issues warning #2942 to note a potential problem.
The fix is the same as for warning #266. Ensure all functions have prototypes visible in the compilation unit where it is called.
2950: calling "xxxx" through function pointer "yyyy" has undefined behavior
Diagnostic is enabled by default.
Compile the test case below with icc -c -little-endian -diag-warning 2950 t2950.c:
void foo(void) {} void bar(void) { void (*pv)() = (void (*)())foo; // no warning void (*pi)(int) = (void (*)(int))foo; // warning }
Compilation output is as follows:
t2950.c(5): warning #2950: calling "void (*)(void)" through function pointer "void (*)(int)" has undefined behavior void (*pi)(int) = (void (*)(int))foo; // warning ^
Explanation and resolution:
The diagnostic is generated when a function pointer is assigned or cast to an incompatible (in the sense of C standard) function pointer. Calling the method through this function pointer is unsafe in terms of ABI and leads to undefined behavior. Ensure only compatible function pointers are used in the assignment and cast operations.
Explicit cast to incompatible pointer are treated in a special way. Cast is considered as the user responsibility; the diagnostic is disabled by default for explicit casts.
2951: invalid conversion from function pointer type "xxxx" to type "yyyy": prototype-less functions obey stricter rules during invocation
Diagnostic is disabled by default.
Compile the test case below with icc -c -little-endian t2951.c :
#pragma warning (enable: 2951) extern void foo(); void bar() { void (*ptr)(void) = (void (*)(void))foo; }
Compilation output is as follows:
t2951.c(6): warning #2951: invalid conversion from function pointer type "void (*)()" to type "void (*)(void)": prototype-less functions obey stricter rules during invocation void (*ptr)(void) = (void (*)(void))foo; ^
Explanation and resolution:
The warning is generated when a prototype-less method is assigned or cast to a function pointer with a definite prototype. Calls through such function pointer may lead to undefined behavior if a function pointer type is not compatible with the actual type of the prototype-less method. Avoid using functions without a prototype in the code.
18014: Byte order of variable "xxxx" was changed to little-endian/big-endian to resolve mismatch during pointer conversion
Diagnostic is enabled under -resolve-byte-order-mismatch only.
Compile the test case below with icc -big-endian -resolve-byte-order-mismatch -c t18014.c:
#include <stdio.h> void foo() { int i; sscanf("1", "%d", &i); }
Compilation output is as follows:
t18014.c(4): remark #18014: Byte order of variable "i" was changed to little -endian to resolve mismatch during pointer conversion
Explanation and resolution:
There are various situations when byte order mismatch problem may occur. When -resolve-byte-order-mismatch command line option is specified, the compiler makes an attempt to resolve the problem automatically. If it succeeds, the original diagnostic (reporting byte order mismatch problem) is suppressed and the remark #18014 is issued instead. The full list of problems the compiler attempts to solve is described by the following warnings: #1696, #1697, #2324, #2325, #2608.