Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong argument type to a standard library function defined as macro

Here is sample code:

#include <ctype.h>

int main(void)
{
    isalpha("X");
}

My question is: Is this code a constraint violation? Equivalently, is an implementation non-conforming if it does not issue a diagnostic?


Motivation: Multiple major compilers don't warn for this code, even in conforming code. C11 6.5.2.2/2 covers that passing char * to a function with prototype expecting int is a constraint violation.

However it is not clear to me whether the provisions in 7.1.4 allowing a library function to be additionally defined as a macro supersede the requirement of 6.5.2.2/2. Footnote 187 suggests that the macro hides the prototype, but footnotes are non-normative.

The code (isalpha)("X"); does give a diagnostic of course.

like image 446
M.M Avatar asked May 28 '18 11:05

M.M


1 Answers

I think the key here is whether isalpha is allowed to be defined as a macro or not. C11 7.1.4 briefly mentions

Any function declared in a header may be additionally implemented as a function-like macro defined in the header

although this chapter is mostly concerned with naming collisions and multi-threading issues etc. On the other hand, C11 7.4 says:

The header declares several functions useful for classifying and mapping characters.

and C11 7.4.1.2:

int isalpha(int c);

The isalpha function...

My take is that isalpha is to be regarded as a function. Or if implemented as a macro, some manner of type check must be ensured by the implementation.

Given that it is a function, it is pretty clear from there. For all functions, the rules for function call are specified in C11 6.5.2.2:

If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type.

Note the "as if by assignment" part. This leads us to the rules for simple assignment C11 6.5.16.1, constraints. The code in the question would behind the lines be equivalent to an assignment expression such as int c = (char[]){"X"}; where the left operand is an arithmetic type and the right operand is a pointer. No such case can be found anywhere in C11 6.5.16.1.

Therefore the code is a constraint violation of 6.5.16.1.

If a compiler lib chooses to implement isalpha as a macro and thereby loses the type check ability somehow by not performing the normal lvalue conversion of function parameters during assignment, then that library might very well be non-conforming, if the compiler fails to produce a diagnostic message.

like image 114
Lundin Avatar answered Oct 23 '22 09:10

Lundin