Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4503,7 +4503,32 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
E->getType(), !getLangOpts().PointerOverflowDefined, SignedIndices,
E->getExprLoc(), &arrayType, E->getBase());
EltBaseInfo = ArrayLV.getBaseInfo();
EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType());
if (!CGM.getCodeGenOpts().NewStructPathTBAA) {
// Since CodeGenTBAA::getTypeInfoHelper only handles array types for
// new struct path TBAA, we must a use a plain access.
EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType());
} else if (ArrayLV.getTBAAInfo().isMayAlias()) {
EltTBAAInfo = TBAAAccessInfo::getMayAliasInfo();
} else if (ArrayLV.getTBAAInfo().isIncomplete()) {
// The array element is complete, even if the array is not.
EltTBAAInfo = CGM.getTBAAAccessInfo(E->getType());
} else {
// The TBAA access info from the array (base) lvalue is ordinary. We will
// adapt it to create access info for the element.
EltTBAAInfo = ArrayLV.getTBAAInfo();

// We retain the TBAA struct path (BaseType and Offset members) from the
// array. In the TBAA representation, we map any array access to the
// element at index 0, as the index is generally a runtime value. This
// element has the same offset in the base type as the array itself.
// If the array lvalue had no base type, there is no point trying to
// generate one, since an array itself is not a valid base type.

// We also retain the access type from the base lvalue, but the access
// size must be updated to the size of an individual element.
EltTBAAInfo.Size =
getContext().getTypeSizeInChars(E->getType()).getQuantity();
}
} else {
// The base must be a pointer; emit it with an estimate of its alignment.
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ static bool TypeHasMayAlias(QualType QTy) {
return true;
QTy = TT->desugar();
}

// Also consider an array type as may_alias when its element type (at
// any level) is marked as such.
if (auto *ArrayTy = QTy->getAsArrayTypeUnsafe())
if (TypeHasMayAlias(ArrayTy->getElementType()))
return true;

return false;
}

Expand Down
47 changes: 41 additions & 6 deletions clang/test/CodeGen/tbaa-array.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
// RUN: %clang_cc1 -triple x86_64-linux -O1 %s \
// RUN: -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
// RUN: %clang_cc1 -triple x86_64-linux -O1 %s \
// RUN: -new-struct-path-tbaa -emit-llvm -o - | \
// RUN: FileCheck -check-prefix=CHECK-NEW %s
//
Expand All @@ -10,6 +10,12 @@
struct A { int i; };
struct B { A a[1]; };
struct C { int i; int x[3]; };
struct D { int n; int arr[]; }; // flexible array member
extern int AA[]; // incomplete array type

typedef int __attribute__((may_alias)) aliasing_int;
typedef int __attribute__((may_alias)) aliasing_array[10];
struct E { aliasing_int x[4]; aliasing_array y; };

int foo(B *b) {
// CHECK-LABEL: _Z3fooP1B
Expand All @@ -28,25 +34,54 @@ int bar(C *c) {

int bar2(C *c) {
// CHECK-NEW-LABEL: _Z4bar2P1C
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_C_x:!.*]]
return c->x[2];
}

int bar3(C *c, int j) {
// CHECK-NEW-LABEL: _Z4bar3P1Ci
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_C_x]]
return c->x[j];
Comment on lines -37 to 44
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I reading this right that the tag now says we access a 4-byte int in C at offset 4?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the access to any element of the x member array will get this tag.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks.

}

int bar4(D *d) {
// CHECK-NEW-LABEL: _Z4bar4P1D
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
return d->arr[d->n];
}

int bar5(int j) {
// CHECK-NEW-LABEL: _Z4bar5i
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
return AA[2] + AA[j];
}

int bar6(E *e, int j) {
// CHECK-NEW-LABEL: _Z4bar6P1Ei
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_E_x:!.*]]
return e->x[j];
}

int bar7(E *e, int j) {
// CHECK-NEW-LABEL: _Z4bar7P1Ei
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_E_y:!.*]]
return e->y[j];
}

// CHECK-DAG: [[TAG_A_i]] = !{[[TYPE_A:!.*]], [[TYPE_int:!.*]], i64 0}
// CHECK-DAG: [[TYPE_A]] = !{!"_ZTS1A", !{{.*}}, i64 0}
// CHECK-DAG: [[TYPE_int]] = !{!"int", !{{.*}}, i64 0}

// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
// CHECK-NEW-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"}
// CHECK-NEW-DAG: [[TAG_int]] = !{[[TYPE_int]], [[TYPE_int]], i64 0, i64 4}
// CHECK-NEW-DAG: [[TYPE_pointer:!.*]] = !{[[TYPE_char]], i64 8, !"any pointer"}
// CHECK-NEW-DAG: [[TYPE_A:!.*]] = !{[[TYPE_char]], i64 4, !"_ZTS1A", [[TYPE_int]], i64 0, i64 4}
// CHECK-NEW-DAG: [[TAG_A_i]] = !{[[TYPE_A]], [[TYPE_int]], i64 0, i64 4}
// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS1C", [[TYPE_int]], i64 0, i64 4, [[TYPE_int]], i64 4, i64 12}
// CHECK-NEW-DAG: [[TAG_C_i]] = !{[[TYPE_C:!.*]], [[TYPE_int:!.*]], i64 0, i64 4}
// CHECK-NEW-DAG: [[TAG_C_i]] = !{[[TYPE_C]], [[TYPE_int]], i64 0, i64 4}
// CHECK-NEW-DAG: [[TAG_C_x]] = !{[[TYPE_C]], [[TYPE_int]], i64 4, i64 4}
// CHECK-NEW-DAG: [[TYPE_E:!.*]] = !{[[TYPE_char]], i64 56, !"_ZTS1E", [[TYPE_char]], i64 0, i64 16, [[TYPE_char]], i64 16, i64 40}
// CHECK-NEW-DAG: [[TAG_E_x]] = !{[[TYPE_E]], [[TYPE_char]], i64 0, i64 4}
// CHECK-NEW-DAG: [[TAG_E_y]] = !{[[TYPE_E]], [[TYPE_char]], i64 16, i64 4}