diff --git a/src/CppAst.Tests/TestStructs.cs b/src/CppAst.Tests/TestStructs.cs
index 2bfebf7..0810837 100644
--- a/src/CppAst.Tests/TestStructs.cs
+++ b/src/CppAst.Tests/TestStructs.cs
@@ -310,5 +310,46 @@ struct HelloWorld
}
);
}
+
+ [Test]
+ public void TestBitOffsets()
+ {
+ ParseAssert(@"
+struct NormalFields
+{
+ int a;
+ short b;
+ float c;
+};
+
+struct Bitfields
+{
+ int a : 1;
+ int b : 2;
+ int c : 3;
+};
+",
+ compilation =>
+ {
+ Assert.False(compilation.HasErrors);
+
+ void Test(int classIndex, int fieldIndex, int expectedOffset, int expectedBitOffset)
+ {
+ var cppStruct = compilation.Classes[classIndex];
+ var field = cppStruct.Fields[fieldIndex];
+ Assert.AreEqual(expectedOffset, field.Offset);
+ Assert.AreEqual(expectedBitOffset, field.BitOffset);
+ }
+
+ Test(0, 0, 0, 0);
+ Test(0, 1, 4, 32);
+ Test(0, 2, 8, 64);
+
+ Test(1, 0, 0, 0);
+ Test(1, 1, 0, 1);
+ Test(1, 2, 0, 3);
+ }
+ );
+ }
}
}
diff --git a/src/CppAst/CppField.cs b/src/CppAst/CppField.cs
index 1958c6a..32bbd9a 100644
--- a/src/CppAst/CppField.cs
+++ b/src/CppAst/CppField.cs
@@ -71,11 +71,16 @@ public CppField(CppType type, string name)
/// Gets or sets the number of bits for this bit field. Only valid if is true.
///
public int BitFieldWidth { get; set; }
-
+
+ ///
+ /// Gets the offset of the field in bytes.
+ ///
+ public long Offset => BitOffset / 8;
+
///
- /// Gets or sets the offset of the field in bytes.
+ /// Gets or sets the offset of the field in bits.
///
- public long Offset { get; set; }
+ public long BitOffset { get; set; }
///
public override string ToString()
diff --git a/src/CppAst/CppModelBuilder.cs b/src/CppAst/CppModelBuilder.cs
index ba2ec60..fadb1d3 100644
--- a/src/CppAst/CppModelBuilder.cs
+++ b/src/CppAst/CppModelBuilder.cs
@@ -531,13 +531,14 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
// Might not be always correct (with alignment rules),
// but not sure how to recover the offset without recalculating the entire offsets
// BF: disregard the above comment? as we are now aligning using the anonymous struct's AlignOf...
- var offset = 0L;
+ var bitOffset = 0L;
var cppClassContainer = containerContext.Container as CppClass;
if (cppClassContainer is object && cppClassContainer.Fields.Count > 0)
{
var lastField = cppClassContainer.Fields[cppClassContainer.Fields.Count - 1];
- offset = (int)lastField.Offset + lastField.Type.SizeOf;
+ var offset = lastField.Offset + lastField.Type.SizeOf;
offset = Align(offset, cppClass.AlignOf);
+ bitOffset = offset * 8;
static long Align(long offset, long alignment)
{
@@ -551,7 +552,7 @@ static long Align(long offset, long alignment)
Visibility = containerContext.CurrentVisibility,
StorageQualifier = GetStorageQualifier(cursor),
IsAnonymous = true,
- Offset = offset,
+ BitOffset = bitOffset,
};
ParseAttributes(cursor, cppField, true);
containerContext.DeclarationContainer.Fields.Add(cppField);
@@ -1154,7 +1155,7 @@ private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCu
cppField = previousField;
cppField.Name = fieldName;
cppField.Type = type;
- cppField.Offset = cursor.OffsetOfField / 8;
+ cppField.BitOffset = cursor.OffsetOfField;
}
else
{
@@ -1164,7 +1165,7 @@ private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCu
StorageQualifier = GetStorageQualifier(cursor),
IsBitField = cursor.IsBitField,
BitFieldWidth = cursor.FieldDeclBitWidth,
- Offset = cursor.OffsetOfField / 8,
+ BitOffset = cursor.OffsetOfField,
};
containerContext.DeclarationContainer.Fields.Add(cppField);
ParseAttributes(cursor, cppField, true);
@@ -1188,7 +1189,7 @@ private void AddAnonymousTypeWithField(CppContainerContext containerContext, CXC
Visibility = GetVisibility(cursor.CXXAccessSpecifier),
StorageQualifier = GetStorageQualifier(cursor),
IsAnonymous = true,
- Offset = cursor.OffsetOfField / 8,
+ BitOffset = cursor.OffsetOfField,
};
containerContext.DeclarationContainer.Fields.Add(cppField);
ParseAttributes(cursor, cppField, true);