Skip to content

Commit ad950e6

Browse files
committed
[TBAA] Only emit pointer tbaa metedata for record types. (llvm#116991)
Be conservative if the type isn't a record type. Handling other types may require stripping const-qualifiers inside the type, e.g. MemberPointerType. Also look through array types same as through pointer types, to not pessimize arrays of pointers. Without this, we assign different tags to the accesses for p an q in the second test in cwg158. PR: llvm#116991 (cherry picked from commit decb874)
1 parent f38772a commit ad950e6

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

clang/lib/CodeGen/CodeGenTBAA.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,27 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
207207
llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size);
208208
if (!CodeGenOpts.PointerTBAA)
209209
return AnyPtr;
210-
// Compute the depth of the pointer and generate a tag of the form "p<depth>
211-
// <base type tag>".
210+
// C++ [basic.lval]p11 permits objects to accessed through an l-value of
211+
// similar type. Two types are similar under C++ [conv.qual]p2 if the
212+
// decomposition of the types into pointers, member pointers, and arrays has
213+
// the same structure when ignoring cv-qualifiers at each level of the
214+
// decomposition. Meanwhile, C makes T(*)[] and T(*)[N] compatible, which
215+
// would really complicate any attempt to distinguish pointers to arrays by
216+
// their bounds. It's simpler, and much easier to explain to users, to
217+
// simply treat all pointers to arrays as pointers to their element type for
218+
// aliasing purposes. So when creating a TBAA tag for a pointer type, we
219+
// recursively ignore both qualifiers and array types when decomposing the
220+
// pointee type. The only meaningful remaining structure is the number of
221+
// pointer types we encountered along the way, so we just produce the tag
222+
// "p<depth> <base type tag>". If we do find a member pointer type, for now
223+
// we just conservatively bail out with AnyPtr (below) rather than trying to
224+
// create a tag that honors the similar-type rules while still
225+
// distinguishing different kinds of member pointer.
212226
unsigned PtrDepth = 0;
213227
do {
214228
PtrDepth++;
215-
Ty = Ty->getPointeeType().getTypePtr();
229+
Ty = Ty->getPointeeType()->getBaseElementTypeUnsafe();
216230
} while (Ty->isPointerType());
217-
Ty = Context.getBaseElementType(QualType(Ty, 0)).getTypePtr();
218231
assert(!isa<VariableArrayType>(Ty));
219232
// When the underlying type is a builtin type, we compute the pointee type
220233
// string recursively, which is implicitly more forgiving than the standards
@@ -232,6 +245,12 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
232245
->getString();
233246
TyName = Name;
234247
} else {
248+
// Be conservative if the type isn't a RecordType. We are specifically
249+
// required to do this for member pointers until we implement the
250+
// similar-types rule.
251+
if (!Ty->isRecordType())
252+
return AnyPtr;
253+
235254
// For non-builtin types use the mangled name of the canonical type.
236255
llvm::raw_svector_ostream TyOut(TyName);
237256
MangleCtx->mangleCanonicalTypeName(QualType(Ty, 0), TyOut);

clang/test/CXX/drs/cwg158.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
// RUN: %clang_cc1 -triple x86_64-linux -std=c++98 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
2-
// RUN: %clang_cc1 -triple x86_64-linux -std=c++11 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
3-
// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
4-
// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
1+
// RUN: %clang_cc1 -triple x86_64-linux -std=c++98 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck --check-prefixes=CHECK %s
2+
// RUN: %clang_cc1 -triple x86_64-linux -std=c++11 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck --check-prefixes=CHECK %s
3+
// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck --check-prefixes=CHECK %s
4+
// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck --check-prefixes=CHECK %s
5+
// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -pointer-tbaa -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck --check-prefixes=CHECK,POINTER-TBAA %s
56

67
// cwg158: yes
78

89
// CHECK-LABEL: define {{.*}} @_Z1f
910
const int *f(const int * const *p, int **q) {
11+
// CHECK: load ptr, ptr %p.addr
1012
// CHECK: load ptr, {{.*}}, !tbaa ![[INTPTR_TBAA:[^,]*]]
1113
const int *x = *p;
1214
// CHECK: store ptr null, {{.*}}, !tbaa ![[INTPTR_TBAA]]
@@ -18,10 +20,24 @@ struct A {};
1820

1921
// CHECK-LABEL: define {{.*}} @_Z1g
2022
const int *(A::*const *g(const int *(A::* const **p)[3], int *(A::***q)[3]))[3] {
23+
// CHECK: load ptr, ptr %p.addr
2124
// CHECK: load ptr, {{.*}}, !tbaa ![[MEMPTR_TBAA:[^,]*]]
2225
const int *(A::*const *x)[3] = *p;
2326
// CHECK: store ptr null, {{.*}}, !tbaa ![[MEMPTR_TBAA]]
2427
*q = 0;
2528
return x;
2629
}
2730

31+
// CHECK-LABEL: define {{.*}} @_Z1h
32+
const int * h(const int * (*p)[10], int *(*q)[9]) {
33+
// CHECK: load ptr, ptr %p.addr, align 8, !tbaa [[PTRARRAY_TBAA:!.+]]
34+
const int * x = *p[0];
35+
36+
// CHECK: load ptr, ptr %q.addr, align 8, !tbaa [[PTRARRAY_TBAA]]
37+
*q[0] = 0;
38+
return x;
39+
}
40+
41+
// POINTER-TBAA: [[PTRARRAY_TBAA]] = !{[[PTRARRAY_TY:!.+]], [[PTRARRAY_TY]], i64 0}
42+
// POINTER-TBAA: [[PTRARRAY_TY]] = !{!"p2 int", [[ANYPTR:!.+]], i64 0}
43+
// POINTER-TBAA: [[ANYPTR]] = !{!"any pointer"

0 commit comments

Comments
 (0)