Search code examples
cclangllvmsizeof

Is this a bug in LLVM?


I am compiling this code (using clang 3.4.2):

#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>

typedef struct __entry {
    char *name;
    int value;
} entry;

int main(int argv, char **argc) {
            printf("Size of entry: %lu\n", sizeof(entry));
        entry *entry = malloc(sizeof(entry));
        printf("entry is at %lu\n", (uint64_t) entry);
}

and I receive this bitcode:

define i32 @main(i32 %argv, i8** %argc) #0 {
entry:
  %argv.addr = alloca i32, align 4
  %argc.addr = alloca i8**, align 8
  %entry1 = alloca %struct.__entry*, align 8
  store i32 %argv, i32* %argv.addr, align 4
  store i8** %argc, i8*** %argc.addr, align 8
  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([20 x i8]* @.str, i32 0, i32 0), i64 16)
  %call2 = call noalias i8* @malloc(i64 8) #3
  %0 = bitcast i8* %call2 to %struct.__entry*
  store %struct.__entry* %0, %struct.__entry** %entry1, align 8
  %1 = load %struct.__entry** %entry1, align 8
  %2 = ptrtoint %struct.__entry* %1 to i64
  %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str1, i32 0, i32 0), i64 %2)
  ret i32 0
}

The call to printf receives 16 as an argument (which I expected for a struct with two pointers on a 64-bit system). However, the call to malloc receives 8. In C, they both got the same argument. What is going on?


Solution

  • The two invocations of sizeof didn't get the same argument! It only looked like they did at first glance.

    The first sizeof(entry) refers to the type name.

    The second sizeof(entry) refers to the local pointer variable.

    After the variable is defined, you can no longer refer to the type in the block of code.

    And this means that the answer to the headline question is "No — LLVM is following the requirements of the standard".

    One minor quirk: the first sizeof(entry) must have the parentheses because the argument is a type name. The second sizeof(entry) can be written sizeof entry because this argument is the name of a variable not a type. This allows you to confirm that the second occurrence is referring to the variable and not the type.