Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where does Clang stores the difference between int32_t *p and int32_t p[10]?

Tags:

c++

c

clang

I would like to make sure that this type of code

void f1 (int32_t p[10]);
void f2 (int32_t *p);
void b ()
{
    int_32_t a[10];
    f1(a);
    f2(a);
}

does not happen when someone is coding, because when using f2(), you may lose the informations about the bounds of the array. It is one of the MISRA Standard rule.

But the AST-dump makes no difference between the 2 functions declaration :

|-FunctionDecl 0x2204140 <test.cpp:3:1, col:23> f1 'void (int32_t *)'
  | -ParmVarDecl 0x2204040 <col:10, col:22> p 'int32_t *'
|-FunctionDecl 0x2204280 <line:4:1, col:20> f2 'void (int32_t *)'
  | -ParmVarDecl 0x2204200 <col:10, col:19> p 'int32_t *'

I guess that Clang does record somewhere the size of the array (10), but AST-dump seems to inform of the opposite.

Is there some way to differentiate ?

like image 735
Marc-O Avatar asked Jul 29 '14 12:07

Marc-O


3 Answers

The question seems to be based on a misconception. This function declaration

void f1 (int32_t p[10]);

is exactly the same as

void f1 (int32_t* p);

The parameter is a pointer in both cases. There is no size information kept anywhere.

Note that, in C++, you are allowed to have function parameters that are references to an array of a certain size. For example,

void f3(int (&p)[10]);

This signature is not the same as the f1 and f2 shown in your example.

like image 129
juanchopanza Avatar answered Nov 10 '22 09:11

juanchopanza


I guess that Clang does record somewhere the size of the array (10), but AST-dump seems to inform of the opposite.

Your guess is wrong.

Is there some way to differentiate ?

No. There is no difference according to the rules of C and C++. See http://www.c-faq.com/aryptr/aryptrparam.html

like image 1
Jonathan Wakely Avatar answered Nov 10 '22 07:11

Jonathan Wakely


I think you're attacking the problem from the wrong end. The declarations of the functions are equivalent, but that's not a problem since the rule you're after applies to the call site. At the call site you certainly know that the array is passed to a function that takes a pointer and doesn't take the array size in another parameter. From the call site's perspective, both f1 and f2 calls are semantically the same. They are equally safe or unsafe.

The C standard doesn't require the compiler to preserve array bounds information when passing arguments into a function. If there are any array bounds in the function's parameter declarations, they are for human consumption only. The f1 and f2 calls are exactly the same according to MISRA, and they are both wrong. You need to pass both the pointer and the array size explicitly.

If you wish to make a special diagnostic for when f1 is called with a pointer or an array smaller than given size, you'll have to modify the parser and add a custom annotation to the AST. That information could then be picked up by your analyzer.

For any of this to make any sense, you'd also need to add diagnostics when static code analysis indicates that the argument is indexed past the bounds within f1.

like image 1
Kuba hasn't forgotten Monica Avatar answered Nov 10 '22 07:11

Kuba hasn't forgotten Monica