Are unknown types now intentionally casual?

Given the following code:

struct Unknown;
extern struct Unknown Unknown;

struct Unknown *foo(void) {
return &Unknown;
}

And compiling it with a recent (trunk of a few days ago) clang with default options gives (abridged):

%struct.Unknown = type opaque

@Unknown = external dso_local global %struct.Unknown, align 1

; Function Attrs: noinline nounwind optnone uwtable
define dso_local %struct.Unknown* @foo() #0 {
entry:
ret %struct.Unknown* @Unknown
}

Okay, so I think I understand what’s going on there. Now, trying the same input with the same compiler and adding the option -mllvm -opaque-pointers (because opaque pointers are good; I think they are a very worthwhile simplification):

@Unknown = external dso_local global %struct.Unknown, align 1

; Function Attrs: noinline nounwind optnone uwtable
define dso_local ptr @foo() #0 {
entry:
ret ptr @Unknown
}

So that’s mostly clear except one thing I’m not quite clear about: %struct.Unknown is referred to, but not declared anywhere. Is that intentional? Is the rule now intended to be that whenever a %type.name is used that was not declared anywhere, it should be taken to be an opaque type? (I’m fine with that if it is, just figure I better make sure.)

… no, when I feed the second output as input into clang again, it objects to the undeclared type:

(c1) C:\t>clang -mllvm -opaque-pointers 2.ll
2.ll:6:38: error: use of undefined type named ‘struct.Unknown’
@Unknown = external dso_local global %struct.Unknown, align 1
^
1 error generated.

So this seems to be just a bug in this particular version of clang, probably because the opaque pointers conversion is still a work in progress?

… no, when I feed the second output as input into clang again, it objects to the undeclared type:

(c1) C:\t>clang -mllvm -opaque-pointers 2.ll
2.ll:6:38: error: use of undefined type named ‘struct.Unknown’
@Unknown = external dso_local global %struct.Unknown, align 1
^
1 error generated.

So this seems to be just a bug in this particular version of clang, probably because the opaque pointers conversion is still a work in progress?

Yes, this is a bug in the opaque pointers implementation. The TypeFinder does not find the struct type here, because it is neither reachable from the global type, nor the (absent) global initializer, but only from the global value type. We’ll have to port some changes from the ValueEnumerator to the TypeFinder.

Regards,
Nikita

This should be fixed by https://github.com/llvm/llvm-project/commit/2c0fb96254fef2509b66d75290fedafd4adede95. Let me know if you encounter further issues.

Regards,
Nikita