Opaque pointer element type for pointer passed as function argument

I have the following code and I was wondering if at the IR level, can ‘ptr’ be of type ‘struct A’ ?

struct A {
    int x;
    float y;
void use(struct A *a);
int test(struct A *a) {

define dso_local void @test(ptr noundef %a) local_unnamed_addr #0 {
  tail call void @use(ptr noundef %a) #2
  ret void
declare void @use(ptr noundef) local_unnamed_addr #1

The intention of asking this I was looking at escape analysis and want to clear my understanding of scope of pointer element types in context of above example.

My understanding is since the struct type has got eliminated at IR level, ptr can never have ‘struct A’ type. Even if the ptr is passed to external lib function, I can still assume that ptr cannot be of type ‘struct A’ because there exists no definition for it at IR level.

Is my understanding correct?

You probably have no header file in your example, but use and test have external linkage. Other TUs could call use. So struct A must still exist?

yes, you are right(in the sense that this is pre-LTO output). But, for sake of simplicity, if we assume that its post-LTO output, whats your stand on my understanding?

If you just look at the given IR there are only ptrs and no loads and stores. So you cannot know the types of the ptrs.

What is strange that @test seems to be local linkage while @use has external linkage and other TUs can call it with an aggregate.

2 hours later I noticed that use is a declaration and not a definition. It must be defined in another TU. Thus struct A escapes from the local TU.

even though struct type has been eliminated ?

At C-like language struct A escapes. At LLVM IR, you have no knowledge of the types of the ptrs because there are neither loads nor stores. Thus anything can escape through calling use.

1 Like

@nikic could you please help with this? Would like to know your opinion

Does Type based escape analysis help you?

@nikic while that helps a bit, its more focused on getting the required info.

My question was related to more of fundamental question “In absence of any usage of that ptr and absence of struct definition itself, can I assume that ptr cannot be of type struct A ?”

Wait that is weird and I am confused…how can you assume that? Look at the source and see, is your assumption valid at IR?

In general, you must not make impractical assumptions for the design of any analysis or transformation. The assumption needs to be backed by some basis and I don’t see any basis here.

I think you should read Opaque Pointers — LLVM 17.0.0git documentation and its design principles first.

@rightrotate thanks for the valuable input. To back my assumption, I already said that “the struct definition has been deleted” and perhaps no longer required at IR level.

That’s where I am confused.

No. Presence or absence of struct definitions has no semantic meaning at all.


@nikic Thanks

@nikic already replied but I give my 2 cents. Elimination is not associated with any semantics so that does not warrant you to make any assumption. You should not make such assumptions if something is eliminated. Clang might decide to eliminate it, flang may not so are you going to say that one is correct over other? There are tons of other things that may be eliminated, can you make any assumptions about that? No.

In short, please read Opaque Pointers.

1 Like