blob: 2bc4b8a542bf34dd482f39ffe51aa814a41ba8f6 [file] [log] [blame]
Dan Gohman947c9af2010-10-14 23:06:10 +00001//===--- CodeGenTypes.cpp - TBAA information for LLVM CodeGen -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Dan Gohman5419ce62010-10-21 18:49:12 +000010// This is the code that manages TBAA information and defines the TBAA policy
11// for the optimizer to use. Relevant standards text includes:
Dan Gohmanf47df3e2010-10-15 20:54:41 +000012//
13// C99 6.5p7
14// C++ [basic.lval] (p10 in n3126, p15 in some earlier versions)
Dan Gohman947c9af2010-10-14 23:06:10 +000015//
16//===----------------------------------------------------------------------===//
17
18#include "CodeGenTBAA.h"
19#include "clang/AST/ASTContext.h"
Benjamin Kramerea70eb32012-12-01 15:09:41 +000020#include "clang/AST/Attr.h"
Peter Collingbourne0ff0b372011-01-13 18:57:25 +000021#include "clang/AST/Mangle.h"
Benjamin Kramerea70eb32012-12-01 15:09:41 +000022#include "clang/AST/RecordLayout.h"
Saleem Abdulrasool10a49722016-04-08 16:52:00 +000023#include "clang/Frontend/CodeGenOptions.h"
Manman Renc451e572013-04-04 21:53:22 +000024#include "llvm/ADT/SmallSet.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000025#include "llvm/IR/Constants.h"
26#include "llvm/IR/LLVMContext.h"
27#include "llvm/IR/Metadata.h"
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +000028#include "llvm/IR/Module.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000029#include "llvm/IR/Type.h"
Dan Gohman947c9af2010-10-14 23:06:10 +000030using namespace clang;
31using namespace CodeGen;
32
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +000033CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M,
Kostya Serebryany5dd2cfc2012-04-24 06:57:01 +000034 const CodeGenOptions &CGO,
Dan Gohman2e29eb52010-10-15 20:23:12 +000035 const LangOptions &Features, MangleContext &MContext)
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +000036 : Context(Ctx), Module(M), CodeGenOpts(CGO),
37 Features(Features), MContext(MContext), MDHelper(M.getContext()),
38 Root(nullptr), Char(nullptr)
39{}
Dan Gohman947c9af2010-10-14 23:06:10 +000040
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000041CodeGenTBAA::~CodeGenTBAA() {
42}
Dan Gohman947c9af2010-10-14 23:06:10 +000043
Dan Gohman7dfd13c2010-10-25 21:48:30 +000044llvm::MDNode *CodeGenTBAA::getRoot() {
45 // Define the root of the tree. This identifies the tree, so that
46 // if our LLVM IR is linked with LLVM IR from a different front-end
47 // (or a different version of this front-end), their TBAA trees will
48 // remain distinct, and the optimizer will treat them conservatively.
Manman Ren37dec102016-02-11 19:19:18 +000049 if (!Root) {
50 if (Features.CPlusPlus)
51 Root = MDHelper.createTBAARoot("Simple C++ TBAA");
52 else
53 Root = MDHelper.createTBAARoot("Simple C/C++ TBAA");
54 }
Dan Gohman7dfd13c2010-10-25 21:48:30 +000055
56 return Root;
57}
58
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +000059llvm::MDNode *CodeGenTBAA::createScalarTypeNode(StringRef Name,
60 llvm::MDNode *Parent,
61 uint64_t Size) {
62 (void)Size; // TODO: Support generation of size-aware type nodes.
Manman Ren4f755de2013-10-08 00:08:49 +000063 return MDHelper.createTBAAScalarTypeNode(Name, Parent);
Manman Rene1ad74e2013-04-11 23:02:56 +000064}
65
Dan Gohman7dfd13c2010-10-25 21:48:30 +000066llvm::MDNode *CodeGenTBAA::getChar() {
67 // Define the root of the tree for user-accessible memory. C and C++
68 // give special powers to char and certain similar types. However,
69 // these special powers only cover user-accessible memory, and doesn't
70 // include things like vtables.
71 if (!Char)
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +000072 Char = createScalarTypeNode("omnipotent char", getRoot(), /* Size= */ 1);
Dan Gohman7dfd13c2010-10-25 21:48:30 +000073
74 return Char;
75}
76
Dan Gohmanc2897692010-12-13 23:51:08 +000077static bool TypeHasMayAlias(QualType QTy) {
78 // Tagged types have declarations, and therefore may have attributes.
79 if (const TagType *TTy = dyn_cast<TagType>(QTy))
80 return TTy->getDecl()->hasAttr<MayAliasAttr>();
81
82 // Typedef types have declarations, and therefore may have attributes.
83 if (const TypedefType *TTy = dyn_cast<TypedefType>(QTy)) {
84 if (TTy->getDecl()->hasAttr<MayAliasAttr>())
85 return true;
86 // Also, their underlying types may have relevant attributes.
87 return TypeHasMayAlias(TTy->desugar());
88 }
89
90 return false;
91}
92
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +000093/// Check if the given type is a valid base type to be used in access tags.
94static bool isValidBaseType(QualType QTy) {
95 if (QTy->isReferenceType())
96 return false;
97 if (const RecordType *TTy = QTy->getAs<RecordType>()) {
98 const RecordDecl *RD = TTy->getDecl()->getDefinition();
99 // Incomplete types are not valid base access types.
100 if (!RD)
101 return false;
102 if (RD->hasFlexibleArrayMember())
103 return false;
Hal Finkela5986b92017-12-03 03:10:13 +0000104 // RD can be struct, union, class, interface or enum.
105 // For now, we only handle struct and class.
106 if (RD->isStruct() || RD->isClass())
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +0000107 return true;
108 }
109 return false;
110}
111
Ivan A. Kosarev5d9d32e2017-11-21 11:18:06 +0000112llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000113 uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity();
114
Dan Gohman5419ce62010-10-21 18:49:12 +0000115 // Handle builtin types.
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000116 if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) {
Dan Gohman947c9af2010-10-14 23:06:10 +0000117 switch (BTy->getKind()) {
Dan Gohmanf5c5e072010-10-15 17:52:03 +0000118 // Character types are special and can alias anything.
119 // In C++, this technically only includes "char" and "unsigned char",
120 // and not "signed char". In C, it includes all three. For now,
Dan Gohman4a3b1b32010-10-15 20:24:10 +0000121 // the risk of exploiting this detail in C++ seems likely to outweigh
Dan Gohmanf5c5e072010-10-15 17:52:03 +0000122 // the benefit.
Dan Gohman947c9af2010-10-14 23:06:10 +0000123 case BuiltinType::Char_U:
124 case BuiltinType::Char_S:
125 case BuiltinType::UChar:
126 case BuiltinType::SChar:
Dan Gohman7dfd13c2010-10-25 21:48:30 +0000127 return getChar();
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000128
129 // Unsigned types can alias their corresponding signed types.
130 case BuiltinType::UShort:
Ivan A. Kosarev289574e2017-10-02 09:54:47 +0000131 return getTypeInfo(Context.ShortTy);
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000132 case BuiltinType::UInt:
Ivan A. Kosarev289574e2017-10-02 09:54:47 +0000133 return getTypeInfo(Context.IntTy);
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000134 case BuiltinType::ULong:
Ivan A. Kosarev289574e2017-10-02 09:54:47 +0000135 return getTypeInfo(Context.LongTy);
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000136 case BuiltinType::ULongLong:
Ivan A. Kosarev289574e2017-10-02 09:54:47 +0000137 return getTypeInfo(Context.LongLongTy);
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000138 case BuiltinType::UInt128:
Ivan A. Kosarev289574e2017-10-02 09:54:47 +0000139 return getTypeInfo(Context.Int128Ty);
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000140
Dan Gohman2d0a3c72010-10-15 20:24:53 +0000141 // Treat all other builtin types as distinct types. This includes
142 // treating wchar_t, char16_t, and char32_t as distinct from their
143 // "underlying types".
Dan Gohman947c9af2010-10-14 23:06:10 +0000144 default:
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000145 return createScalarTypeNode(BTy->getName(Features), getChar(), Size);
Dan Gohman947c9af2010-10-14 23:06:10 +0000146 }
147 }
148
David Majnemer8f94a232017-07-25 23:33:58 +0000149 // C++1z [basic.lval]p10: "If a program attempts to access the stored value of
150 // an object through a glvalue of other than one of the following types the
151 // behavior is undefined: [...] a char, unsigned char, or std::byte type."
152 if (Ty->isStdByteType())
Ivan A. Kosarev5d9d32e2017-11-21 11:18:06 +0000153 return getChar();
David Majnemer8f94a232017-07-25 23:33:58 +0000154
Ivan A. Kosarevb75a50b2017-09-26 14:22:48 +0000155 // Handle pointers and references.
Dan Gohmanc44fd642010-10-15 20:26:20 +0000156 // TODO: Implement C++'s type "similarity" and consider dis-"similar"
157 // pointers distinct.
Ivan A. Kosarevb75a50b2017-09-26 14:22:48 +0000158 if (Ty->isPointerType() || Ty->isReferenceType())
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000159 return createScalarTypeNode("any pointer", getChar(), Size);
Dan Gohmand65c1962010-10-15 00:01:39 +0000160
Dan Gohman2e29eb52010-10-15 20:23:12 +0000161 // Enum types are distinct types. In C++ they have "underlying types",
162 // however they aren't related for TBAA.
163 if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) {
Dan Gohman2e29eb52010-10-15 20:23:12 +0000164 // In C++ mode, types have linkage, so we can rely on the ODR and
165 // on their mangled names, if they're external.
166 // TODO: Is there a way to get a program-wide unique name for a
167 // decl with local linkage or no linkage?
Eli Friedmaneecc09a2013-07-05 20:27:40 +0000168 if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible())
Ivan A. Kosarev5d9d32e2017-11-21 11:18:06 +0000169 return getChar();
Dan Gohman2e29eb52010-10-15 20:23:12 +0000170
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000171 SmallString<256> OutName;
Rafael Espindola3968cd02011-02-11 02:52:17 +0000172 llvm::raw_svector_ostream Out(OutName);
Reid Klecknercc99e262013-11-19 23:23:00 +0000173 MContext.mangleTypeName(QualType(ETy, 0), Out);
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000174 return createScalarTypeNode(OutName, getChar(), Size);
Dan Gohman2e29eb52010-10-15 20:23:12 +0000175 }
176
Dan Gohman3f1cf0f2010-10-14 23:39:00 +0000177 // For now, handle any other kind of type conservatively.
Ivan A. Kosarev5d9d32e2017-11-21 11:18:06 +0000178 return getChar();
179}
180
181llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
182 // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
183 if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
184 return nullptr;
185
186 // If the type has the may_alias attribute (even on a typedef), it is
187 // effectively in the general char alias class.
188 if (TypeHasMayAlias(QTy))
189 return getChar();
190
191 // We need this function to not fall back to returning the "omnipotent char"
192 // type node for aggregate and union types. Otherwise, any dereference of an
193 // aggregate will result into the may-alias access descriptor, meaning all
194 // subsequent accesses to direct and indirect members of that aggregate will
195 // be considered may-alias too.
196 // TODO: Combine getTypeInfo() and getBaseTypeInfo() into a single function.
197 if (isValidBaseType(QTy))
198 return getBaseTypeInfo(QTy);
199
200 const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
201 if (llvm::MDNode *N = MetadataCache[Ty])
202 return N;
203
204 // Note that the following helper call is allowed to add new nodes to the
205 // cache, which invalidates all its previously obtained iterators. So we
206 // first generate the node for the type and then add that node to the cache.
207 llvm::MDNode *TypeNode = getTypeInfoHelper(Ty);
208 return MetadataCache[Ty] = TypeNode;
Dan Gohman947c9af2010-10-14 23:06:10 +0000209}
Kostya Serebryany141e46f2012-03-26 17:03:51 +0000210
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000211TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo(llvm::Type *VTablePtrType) {
212 llvm::DataLayout DL(&Module);
213 unsigned Size = DL.getPointerTypeSize(VTablePtrType);
214 return TBAAAccessInfo(createScalarTypeNode("vtable pointer", getRoot(), Size),
215 Size);
Kostya Serebryany141e46f2012-03-26 17:03:51 +0000216}
Dan Gohman22695fc2012-09-28 21:58:29 +0000217
218bool
219CodeGenTBAA::CollectFields(uint64_t BaseOffset,
220 QualType QTy,
221 SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &
222 Fields,
223 bool MayAlias) {
224 /* Things not handled yet include: C++ base classes, bitfields, */
225
226 if (const RecordType *TTy = QTy->getAs<RecordType>()) {
227 const RecordDecl *RD = TTy->getDecl()->getDefinition();
228 if (RD->hasFlexibleArrayMember())
229 return false;
230
231 // TODO: Handle C++ base classes.
232 if (const CXXRecordDecl *Decl = dyn_cast<CXXRecordDecl>(RD))
233 if (Decl->bases_begin() != Decl->bases_end())
234 return false;
235
236 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
237
238 unsigned idx = 0;
239 for (RecordDecl::field_iterator i = RD->field_begin(),
240 e = RD->field_end(); i != e; ++i, ++idx) {
241 uint64_t Offset = BaseOffset +
242 Layout.getFieldOffset(idx) / Context.getCharWidth();
243 QualType FieldQTy = i->getType();
244 if (!CollectFields(Offset, FieldQTy, Fields,
245 MayAlias || TypeHasMayAlias(FieldQTy)))
246 return false;
247 }
248 return true;
249 }
250
251 /* Otherwise, treat whatever it is as a field. */
252 uint64_t Offset = BaseOffset;
253 uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
Ivan A. Kosarev3d68ce92017-10-05 11:08:17 +0000254 llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy);
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000255 llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
Manman Ren09a39122013-04-22 19:50:07 +0000256 Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
Dan Gohman22695fc2012-09-28 21:58:29 +0000257 return true;
258}
259
260llvm::MDNode *
261CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
262 const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
263
264 if (llvm::MDNode *N = StructMetadataCache[Ty])
265 return N;
266
267 SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
268 if (CollectFields(0, QTy, Fields, TypeHasMayAlias(QTy)))
269 return MDHelper.createTBAAStructNode(Fields);
270
271 // For now, handle any other kind of type conservatively.
Craig Topper8a13c412014-05-21 05:09:00 +0000272 return StructMetadataCache[Ty] = nullptr;
Dan Gohman22695fc2012-09-28 21:58:29 +0000273}
Manman Renc451e572013-04-04 21:53:22 +0000274
Ivan A. Kosarev5d9d32e2017-11-21 11:18:06 +0000275llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
276 if (auto *TTy = dyn_cast<RecordType>(Ty)) {
Manman Renc451e572013-04-04 21:53:22 +0000277 const RecordDecl *RD = TTy->getDecl()->getDefinition();
Manman Renc451e572013-04-04 21:53:22 +0000278 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000279 SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
Hal Finkela5986b92017-12-03 03:10:13 +0000280 for (FieldDecl *Field : RD->fields()) {
281 QualType FieldQTy = Field->getType();
282 llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
283 getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
284 if (!TypeNode)
285 return BaseTypeMetadataCache[Ty] = nullptr;
Ivan A. Kosarevda342472017-11-30 09:26:39 +0000286
Hal Finkela5986b92017-12-03 03:10:13 +0000287 uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
288 uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
289 uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
290 Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
291 TypeNode));
Manman Renc451e572013-04-04 21:53:22 +0000292 }
293
Manman Renc451e572013-04-04 21:53:22 +0000294 SmallString<256> OutName;
Manman Ren879ce882013-08-21 20:58:45 +0000295 if (Features.CPlusPlus) {
Reid Klecknercc99e262013-11-19 23:23:00 +0000296 // Don't use the mangler for C code.
Manman Ren879ce882013-08-21 20:58:45 +0000297 llvm::raw_svector_ostream Out(OutName);
Reid Klecknercc99e262013-11-19 23:23:00 +0000298 MContext.mangleTypeName(QualType(Ty, 0), Out);
Manman Ren879ce882013-08-21 20:58:45 +0000299 } else {
300 OutName = RD->getName();
301 }
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000302
303 // TODO: Support size-aware type nodes and create one here for the
304 // given aggregate type.
305
Manman Renc451e572013-04-04 21:53:22 +0000306 // Create the struct type node with a vector of pairs (offset, type).
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000307 SmallVector<std::pair<llvm::MDNode*, uint64_t>, 4> OffsetsAndTypes;
308 for (const auto &Field : Fields)
309 OffsetsAndTypes.push_back(std::make_pair(Field.TBAA, Field.Offset));
310 return MDHelper.createTBAAStructTypeNode(OutName, OffsetsAndTypes);
Manman Renc451e572013-04-04 21:53:22 +0000311 }
312
Ivan A. Kosarev5d9d32e2017-11-21 11:18:06 +0000313 return nullptr;
314}
315
316llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
317 if (!isValidBaseType(QTy))
318 return nullptr;
319
320 const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
321 if (llvm::MDNode *N = BaseTypeMetadataCache[Ty])
322 return N;
323
324 // Note that the following helper call is allowed to add new nodes to the
325 // cache, which invalidates all its previously obtained iterators. So we
326 // first generate the node for the type and then add that node to the cache.
327 llvm::MDNode *TypeNode = getBaseTypeInfoHelper(Ty);
328 return BaseTypeMetadataCache[Ty] = TypeNode;
Manman Renc451e572013-04-04 21:53:22 +0000329}
330
Ivan A. Kosarev3d68ce92017-10-05 11:08:17 +0000331llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000332 assert(!Info.isIncomplete() && "Access to an object of an incomplete type!");
333
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +0000334 if (Info.isMayAlias())
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000335 Info = TBAAAccessInfo(getChar(), Info.Size);
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +0000336
Ivan A. Kosareva511ed72017-10-03 10:52:39 +0000337 if (!Info.AccessType)
Craig Topper8a13c412014-05-21 05:09:00 +0000338 return nullptr;
Manman Ren4f755de2013-10-08 00:08:49 +0000339
Manman Renc451e572013-04-04 21:53:22 +0000340 if (!CodeGenOpts.StructPathTBAA)
Ivan A. Kosarev4e50e702017-11-27 09:39:29 +0000341 Info = TBAAAccessInfo(Info.AccessType, Info.Size);
Manman Renc451e572013-04-04 21:53:22 +0000342
Ivan A. Kosarev383890b2017-10-06 08:17:48 +0000343 llvm::MDNode *&N = AccessTagMetadataCache[Info];
344 if (N)
Manman Renc451e572013-04-04 21:53:22 +0000345 return N;
346
Ivan A. Kosarev383890b2017-10-06 08:17:48 +0000347 if (!Info.BaseType) {
348 Info.BaseType = Info.AccessType;
349 assert(!Info.Offset && "Nonzero offset for an access with no base type!");
350 }
351 return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType,
352 Info.Offset);
Manman Renc451e572013-04-04 21:53:22 +0000353}
Manman Rene1ad74e2013-04-11 23:02:56 +0000354
Ivan A. Kosareved141ba2017-10-17 09:12:13 +0000355TBAAAccessInfo CodeGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
356 TBAAAccessInfo TargetInfo) {
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +0000357 if (SourceInfo.isMayAlias() || TargetInfo.isMayAlias())
358 return TBAAAccessInfo::getMayAliasInfo();
Ivan A. Kosareved141ba2017-10-17 09:12:13 +0000359 return TargetInfo;
360}
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +0000361
362TBAAAccessInfo
363CodeGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
364 TBAAAccessInfo InfoB) {
365 if (InfoA == InfoB)
366 return InfoA;
367
368 if (!InfoA || !InfoB)
369 return TBAAAccessInfo();
370
371 if (InfoA.isMayAlias() || InfoB.isMayAlias())
372 return TBAAAccessInfo::getMayAliasInfo();
373
374 // TODO: Implement the rest of the logic here. For example, two accesses
375 // with same final access types result in an access to an object of that final
376 // access type regardless of their base types.
377 return TBAAAccessInfo::getMayAliasInfo();
378}