The tbaa metadata for structure field array access

Hello,

I have one question regarding the tbaa metadata !8 used for the load HdFree->name[0] in the following example.
Apparently the tbaa metadata !8 = !{!3, !3, i64 0} has lost the structure field information. Why not !8 = !{!6, !3, i64 16}?

If the structure field name is a scalar, the clang will generate accurate meta data. Why does the clang generate
conservative metadata for the array fields?

Thanks,

Jin

typedef struct TypHeader {
unsigned long size;
struct TypHeader * * ptr;
char name[3];
unsigned char type;
} * TypHandle;

TypHandle HdFree;

void foo(unsigned long s, unsigned char c, struct TypHeader * *p){
HdFree->size = s;
HdFree->ptr = p;
HdFree->name[0] = 10;
HdFree->type = c;

}

target datalayout = “e-m:e-i64:64-f80:128-n8:16:32:64-S128”
target triple = “x86_64-unknown-linux-gnu”

%struct.TypHeader = type { i64, %struct.TypHeader**, [3 x i8], i8 }

@HdFree = common global %struct.TypHeader* null, align 8

; Function Attrs: nounwind uwtable
define void @foo(i64 %s, i8 zeroext %c) #0 {
entry:
%0 = load %struct.TypHeader*, %struct.TypHeader** @HdFree, align 8, !tbaa !1
%size = getelementptr inbounds %struct.TypHeader, %struct.TypHeader* %0, i64 0, i32 0
store i64 %s, i64* %size, align 8, !tbaa !5
%arrayidx = getelementptr inbounds %struct.TypHeader, %struct.TypHeader* %0, i64 0, i32 2, i64 0
store i8 102, i8* %arrayidx, align 8, !tbaa !8
%1 = load %struct.TypHeader*, %struct.TypHeader** @HdFree, align 8, !tbaa !1
%arrayidx2 = getelementptr inbounds %struct.TypHeader, %struct.TypHeader* %1, i64 0, i32 2, i64 1
store i8 114, i8* %arrayidx2, align 1, !tbaa !8
%2 = load %struct.TypHeader*, %struct.TypHeader** @HdFree, align 8, !tbaa !1
%arrayidx4 = getelementptr inbounds %struct.TypHeader, %struct.TypHeader* %2, i64 0, i32 2, i64 2
store i8 101, i8* %arrayidx4, align 2, !tbaa !8
%3 = load %struct.TypHeader*, %struct.TypHeader** @HdFree, align 8, !tbaa !1
%type = getelementptr inbounds %struct.TypHeader, %struct.TypHeader* %3, i64 0, i32 3
store i8 %c, i8* %type, align 1, !tbaa !9
ret void
}

attributes #0 = { nounwind uwtable “disable-tail-calls”=“false” “less-precise-fpmad”=“false” “no-frame-pointer-elim”=“false” “no-infs-fp-math”=“false” “no-nans-fp-math”=“false” “stack-protector-buffer-size”=“8” “target-cpu”=“x86-64” “target-features”=“+sse,+sse2” “unsafe-fp-math”=“false” “use-soft-float”=“false” }

!llvm.ident = !{!0}

!0 = !{!“clang version 3.8.0 (trunk 1545)”}
!1 = !{!2, !2, i64 0}
!2 = !{!“any pointer”, !3, i64 0}
!3 = !{!“omnipotent char”, !4, i64 0}
!4 = !{!“Simple C/C++ TBAA”}
!5 = !{!6, !7, i64 0}
!6 = !{!“TypHeader”, !7, i64 0, !2, i64 8, !3, i64 16, !3, i64 19}
!7 = !{!“long”, !3, i64 0}
!8 = !{!3, !3, i64 0}
!9 = !{!6, !3, i64 19}