diff --git a/clang/lib/CodeGen/CodeGenTBAA.h b/clang/lib/CodeGen/CodeGenTBAA.h --- a/clang/lib/CodeGen/CodeGenTBAA.h +++ b/clang/lib/CodeGen/CodeGenTBAA.h @@ -146,6 +146,12 @@ /// considered to be equivalent to it. llvm::MDNode *getChar(); + /// AddCollectedField - Add one collected field to Fields vector + void + AddCollectedField(SmallVectorImpl &Fields, + uint64_t Offset, uint64_t Size, QualType QTy, bool MayAlias, + bool FuseOverlapping); + /// CollectFields - Collect information about the fields of a type for /// !tbaa.struct metadata formation. Return false for an unsupported type. bool CollectFields(uint64_t BaseOffset, diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -272,13 +272,28 @@ Size); } +void CodeGenTBAA::AddCollectedField( + SmallVectorImpl &Fields, uint64_t Offset, + uint64_t Size, QualType QTy, bool MayAlias, bool FuseOverlapping) { + + // Fuse fields that overlap in their byte position (e.g. caused by bitfields) + if (FuseOverlapping && !Fields.empty() && Offset < Fields.back().Offset + Fields.back().Size) { + Fields.back().Size = Fields.back().Offset - Offset + Size; + return; + } + + llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy); + llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size)); + Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag)); +} + bool CodeGenTBAA::CollectFields(uint64_t BaseOffset, QualType QTy, SmallVectorImpl & Fields, bool MayAlias) { - /* Things not handled yet include: C++ base classes, bitfields, */ + /* Things not handled yet include: C++ base classes */ if (const RecordType *TTy = QTy->getAs()) { const RecordDecl *RD = TTy->getDecl()->getDefinition(); @@ -300,19 +315,25 @@ uint64_t Offset = BaseOffset + Layout.getFieldOffset(idx) / Context.getCharWidth(); QualType FieldQTy = i->getType(); - if (!CollectFields(Offset, FieldQTy, Fields, - MayAlias || TypeHasMayAlias(FieldQTy))) - return false; + bool FieldMayAlias = MayAlias || TypeHasMayAlias(FieldQTy); + if ((*i)->isBitField()) { + uint64_t EndOffset = + BaseOffset + + (Layout.getFieldOffset(idx) + (*i)->getBitWidthValue(Context) - 1) / + Context.getCharWidth(); + + AddCollectedField(Fields, Offset, EndOffset - Offset + 1, QTy, FieldMayAlias, true); + } else { + if (!CollectFields(Offset, FieldQTy, Fields, FieldMayAlias)) + return false; + } } return true; } /* Otherwise, treat whatever it is as a field. */ - uint64_t Offset = BaseOffset; uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity(); - llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy); - llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size)); - Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag)); + AddCollectedField(Fields, BaseOffset, Size, QTy, MayAlias, false); return true; }