From 411d33aa0b0d3bc9b2faec40cd821bdd836094ab Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 11 Apr 2013 01:20:11 +0000 Subject: [libclang] Expose record layout info via new libclang functions: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clang_Type_getAlignOf clang_Type_getSizeOf clang_Type_getOffsetOf clang_Cursor_isBitField Patch by Loïc Jaquemet! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179251 91177308-0d34-0410-b5e6-96231b3b80d8 --- bindings/python/clang/cindex.py | 50 ++++++++++++++++++++++++ bindings/python/tests/cindex/test_type.py | 63 +++++++++++++++++++++++++++++++ bindings/python/tests/cindex/util.py | 4 +- 3 files changed, 115 insertions(+), 2 deletions(-) (limited to 'bindings') diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 70f4f36a2c..36761bd859 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -1314,6 +1314,18 @@ class Cursor(Structure): """ return TokenGroup.get_tokens(self._tu, self.extent) + def is_bitfield(self): + """ + Check if the field is a bitfield. + """ + return conf.lib.clang_Cursor_isBitField(self) + + def get_bitfield_width(self): + """ + Retrieve the width of a bitfield. + """ + return conf.lib.clang_getFieldDeclBitWidth(self) + @staticmethod def from_result(res, fn, args): assert isinstance(res, Cursor) @@ -1613,6 +1625,24 @@ class Type(Structure): """ return conf.lib.clang_getArraySize(self) + def get_align(self): + """ + Retrieve the alignment of the record. + """ + return conf.lib.clang_Type_getAlignOf(self) + + def get_size(self): + """ + Retrieve the size of the record. + """ + return conf.lib.clang_Type_getSizeOf(self) + + def get_offset(self, fieldname): + """ + Retrieve the offset of a field in the record. + """ + return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname)) + def __eq__(self, other): if type(other) != type(self): return False @@ -2623,6 +2653,10 @@ functionList = [ [Type], c_longlong), + ("clang_getFieldDeclBitWidth", + [Cursor], + c_int), + ("clang_getCanonicalCursor", [Cursor], Cursor, @@ -3038,6 +3072,22 @@ functionList = [ [Cursor, c_uint], Cursor, Cursor.from_result), + + ("clang_Cursor_isBitField", + [Cursor], + c_long), + + ("clang_Type_getAlignOf", + [Type], + c_longlong), + + ("clang_Type_getOffsetOf", + [Type, c_char_p], + c_longlong), + + ("clang_Type_getSizeOf", + [Type], + c_ulonglong), ] class LibclangError(Exception): diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py index 28e4411c77..9bbed5aa94 100644 --- a/bindings/python/tests/cindex/test_type.py +++ b/bindings/python/tests/cindex/test_type.py @@ -298,3 +298,66 @@ def test_is_restrict_qualified(): assert isinstance(i.type.is_restrict_qualified(), bool) assert i.type.is_restrict_qualified() assert not j.type.is_restrict_qualified() + +def test_record_layout(): + """Ensure Cursor.type.get_size, Cursor.type.get_align and + Cursor.type.get_offset works.""" + + source =""" +struct a { + long a1; + long a2:3; + long a3:4; + long long a4; +}; +""" + tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)), + (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)), + (['-target','i386-pc-win32'],(8,16,0,32,35,64)), + (['-target','msp430-none-none'],(2,14,0,32,35,48))] + for flags, values in tries: + align,total,a1,a2,a3,a4 = values + + tu = get_tu(source, flags=flags) + teststruct = get_cursor(tu, 'a') + fields = list(teststruct.get_children()) + + assert teststruct.type.get_align() == align + assert teststruct.type.get_size() == total + assert teststruct.type.get_offset(fields[0].spelling) == a1 + assert teststruct.type.get_offset(fields[1].spelling) == a2 + assert teststruct.type.get_offset(fields[2].spelling) == a3 + assert teststruct.type.get_offset(fields[3].spelling) == a4 + assert fields[0].is_bitfield() == False + assert fields[1].is_bitfield() == True + assert fields[1].get_bitfield_width() == 3 + assert fields[2].is_bitfield() == True + assert fields[2].get_bitfield_width() == 4 + assert fields[3].is_bitfield() == False + +def test_offset(): + """Ensure Cursor.get_record_field_offset works in anonymous records""" + source=""" +struct Test { + struct { + int bariton; + union { + int foo; + }; + }; + int bar; +};""" + tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64)), + (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64)), + (['-target','i386-pc-win32'],(8,16,0,32,64)), + (['-target','msp430-none-none'],(2,14,0,32,64))] + for flags, values in tries: + align,total,bariton,foo,bar = values + tu = get_tu(source) + teststruct = get_cursor(tu, 'Test') + fields = list(teststruct.get_children()) + assert teststruct.type.get_offset("bariton") == bariton + assert teststruct.type.get_offset("foo") == foo + assert teststruct.type.get_offset("bar") == bar + + diff --git a/bindings/python/tests/cindex/util.py b/bindings/python/tests/cindex/util.py index 2323839306..8614b02ad2 100644 --- a/bindings/python/tests/cindex/util.py +++ b/bindings/python/tests/cindex/util.py @@ -3,7 +3,7 @@ from clang.cindex import Cursor from clang.cindex import TranslationUnit -def get_tu(source, lang='c', all_warnings=False): +def get_tu(source, lang='c', all_warnings=False, flags=[]): """Obtain a translation unit from source and language. By default, the translation unit is created from source file "t." @@ -14,8 +14,8 @@ def get_tu(source, lang='c', all_warnings=False): all_warnings is a convenience argument to enable all compiler warnings. """ + args = list(flags) name = 't.c' - args = [] if lang == 'cpp': name = 't.cpp' args.append('-std=c++11') -- cgit v1.2.3-18-g5258