summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenTBAA.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CodeGenTBAA.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenTBAA.cpp42
1 files changed, 28 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 2bc4b8a542b..80ad9aecfed 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -74,6 +74,10 @@ llvm::MDNode *CodeGenTBAA::getChar() {
return Char;
}
+llvm::MDNode *CodeGenTBAA::getUnionMemberType(uint64_t Size) {
+ return createScalarTypeNode("union member", getChar(), Size);
+}
+
static bool TypeHasMayAlias(QualType QTy) {
// Tagged types have declarations, and therefore may have attributes.
if (const TagType *TTy = dyn_cast<TagType>(QTy))
@@ -101,9 +105,8 @@ static bool isValidBaseType(QualType QTy) {
return false;
if (RD->hasFlexibleArrayMember())
return false;
- // RD can be struct, union, class, interface or enum.
- // For now, we only handle struct and class.
- if (RD->isStruct() || RD->isClass())
+ // For now, we do not allow interface classes to be base access types.
+ if (RD->isStruct() || RD->isClass() || RD->isUnion())
return true;
}
return false;
@@ -277,18 +280,27 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
- for (FieldDecl *Field : RD->fields()) {
- QualType FieldQTy = Field->getType();
- llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
- getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
- if (!TypeNode)
- return BaseTypeMetadataCache[Ty] = nullptr;
-
- uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
- uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
- uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
- Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
+ if (RD->isUnion()) {
+ // Unions are represented as structures with a single member that has a
+ // special type and occupies the whole object.
+ uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity();
+ llvm::MDNode *TypeNode = getUnionMemberType(Size);
+ Fields.push_back(llvm::MDBuilder::TBAAStructField(/* Offset= */ 0, Size,
TypeNode));
+ } else {
+ for (FieldDecl *Field : RD->fields()) {
+ QualType FieldQTy = Field->getType();
+ llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
+ getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
+ if (!TypeNode)
+ return nullptr;
+
+ uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
+ uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
+ uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
+ Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
+ TypeNode));
+ }
}
SmallString<256> OutName;
@@ -333,6 +345,8 @@ llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
if (Info.isMayAlias())
Info = TBAAAccessInfo(getChar(), Info.Size);
+ else if (Info.isUnionMember())
+ Info.AccessType = getUnionMemberType(Info.Size);
if (!Info.AccessType)
return nullptr;
OpenPOWER on IntegriCloud