[llvm-dev] broken C code only when optimized "-O2"

Adrian Moreno via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 22 02:05:25 PST 2021


Hi,

I have a suspicion of what could be causing the problem, I'd like to run through 
you to get your feedback from the compiler pov.

One of the things that originally felt smelly was that the fact that the macros 
that iterate the list elements assume the "struct ovs_list" element is embedded 
into another "struct member":

struct member *pos = 0;

for ((((pos) = ((struct member *) (void *) ((uintptr_t)(void *)((&start)->next) 
- __builtin_offsetof (struct member, elem)))));
      &(pos)->elem != (&start);
      ((pos) = ((struct member *) (void *) ((uintptr_t)(void 
*)((pos)->elem.next) - __builtin_offsetof (struct member , elem)
)))) {
    [... use pos ]
      }

however, the first node in the list ("start") is a "struct ovs_list" defined in 
the stack and _not_ embedded into a "struct member".

Therefore, "(&start)->next - __builtin_offsetof (struct member, elem)" actually 
points to somewhere in the stack that contains who knows what. (Note: initially 
start->next = start)

In fact, if I make the struct offsets zero:

struct member {
     struct ovs_list elem;
     [ ... ]
     int order;
};

... the code works. However if I use:

struct member {
     int padding[10];
     struct ovs_list elem;
     [ ... ]
     int order;
};

... the code fails.

Does anything of what I'm saying make sense so far?

If the code inside the loop just made use of "pos" through "(&pos->elem)" then 
the compiler could(?) be ok with it but the loop actually contains:
            if (member->order > pos->order) {
                break;
            }

So here I do not know what the compiler would think about "pos" if it happens to 
point to some invalid stack address.

Thanks for the help.

-- 
Adrián Moreno



More information about the llvm-dev mailing list