ffi-clang 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ext/rakefile.rb +2 -2
- data/lib/ffi/clang/clang_version.rb +7 -3
- data/lib/ffi/clang/code_completion.rb +121 -44
- data/lib/ffi/clang/comment.rb +164 -57
- data/lib/ffi/clang/compilation_database.rb +79 -25
- data/lib/ffi/clang/cursor.rb +395 -149
- data/lib/ffi/clang/diagnostic.rb +57 -23
- data/lib/ffi/clang/error.rb +12 -0
- data/lib/ffi/clang/file.rb +30 -11
- data/lib/ffi/clang/index.rb +37 -13
- data/lib/ffi/clang/lib/clang_version.rb +2 -2
- data/lib/ffi/clang/lib/code_completion.rb +15 -11
- data/lib/ffi/clang/lib/comment.rb +16 -14
- data/lib/ffi/clang/lib/compilation_database.rb +5 -5
- data/lib/ffi/clang/lib/cursor.rb +74 -56
- data/lib/ffi/clang/lib/diagnostic.rb +14 -14
- data/lib/ffi/clang/lib/file.rb +10 -6
- data/lib/ffi/clang/lib/inclusions.rb +3 -3
- data/lib/ffi/clang/lib/index.rb +7 -5
- data/lib/ffi/clang/lib/printing_policy.rb +36 -36
- data/lib/ffi/clang/lib/source_location.rb +9 -7
- data/lib/ffi/clang/lib/source_range.rb +5 -3
- data/lib/ffi/clang/lib/string.rb +9 -4
- data/lib/ffi/clang/lib/token.rb +17 -4
- data/lib/ffi/clang/lib/translation_unit.rb +17 -13
- data/lib/ffi/clang/lib/type.rb +19 -17
- data/lib/ffi/clang/lib.rb +35 -19
- data/lib/ffi/clang/platform.rb +25 -0
- data/lib/ffi/clang/printing_policy.rb +31 -18
- data/lib/ffi/clang/source_location.rb +119 -36
- data/lib/ffi/clang/source_range.rb +30 -12
- data/lib/ffi/clang/token.rb +48 -23
- data/lib/ffi/clang/translation_unit.rb +97 -33
- data/lib/ffi/clang/types/array.rb +15 -1
- data/lib/ffi/clang/types/elaborated.rb +19 -4
- data/lib/ffi/clang/types/function.rb +35 -10
- data/lib/ffi/clang/types/pointer.rb +23 -7
- data/lib/ffi/clang/types/record.rb +23 -8
- data/lib/ffi/clang/types/type.rb +80 -36
- data/lib/ffi/clang/types/type_def.rb +14 -2
- data/lib/ffi/clang/types/vector.rb +13 -1
- data/lib/ffi/clang/unsaved_file.rb +18 -8
- data/lib/ffi/clang/version.rb +4 -2
- data/lib/ffi/clang.rb +23 -45
- data/license.md +3 -2
- data/readme.md +12 -13
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +10 -5
- metadata.gz.sig +0 -0
|
@@ -3,68 +3,94 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2010, by Jari Bakken.
|
|
5
5
|
# Copyright, 2012, by Hal Brodigan.
|
|
6
|
-
# Copyright, 2013-
|
|
6
|
+
# Copyright, 2013-2025, by Samuel Williams.
|
|
7
7
|
# Copyright, 2013, by Garry Marshall.
|
|
8
8
|
# Copyright, 2014, by Masahiro Sano.
|
|
9
9
|
# Copyright, 2014, by Greg Hazel.
|
|
10
10
|
# Copyright, 2019, by Michael Metivier.
|
|
11
11
|
# Copyright, 2022, by Motonori Iwamuro.
|
|
12
12
|
|
|
13
|
-
require_relative
|
|
14
|
-
require_relative
|
|
15
|
-
require_relative
|
|
16
|
-
require_relative
|
|
17
|
-
require_relative
|
|
13
|
+
require_relative "lib/translation_unit"
|
|
14
|
+
require_relative "lib/inclusions"
|
|
15
|
+
require_relative "cursor"
|
|
16
|
+
require_relative "file"
|
|
17
|
+
require_relative "token"
|
|
18
|
+
require_relative "error"
|
|
18
19
|
|
|
19
20
|
module FFI
|
|
20
21
|
module Clang
|
|
22
|
+
# Represents a single translation unit (a compiled source file with its dependencies).
|
|
21
23
|
class TranslationUnit < AutoPointer
|
|
24
|
+
# Initialize a translation unit with a pointer and parent index.
|
|
25
|
+
# @parameter pointer [FFI::Pointer] The translation unit pointer.
|
|
26
|
+
# @parameter index [Index] The parent index that created this translation unit.
|
|
22
27
|
def initialize(pointer, index)
|
|
23
28
|
super pointer
|
|
24
29
|
@index = index
|
|
25
30
|
end
|
|
26
|
-
|
|
31
|
+
|
|
32
|
+
# Release the translation unit pointer.
|
|
33
|
+
# @parameter pointer [FFI::Pointer] The translation unit pointer to release.
|
|
27
34
|
def self.release(pointer)
|
|
28
35
|
Lib.dispose_translation_unit(pointer)
|
|
29
36
|
end
|
|
30
|
-
|
|
37
|
+
|
|
38
|
+
# Get the default editing translation unit options.
|
|
39
|
+
# @returns [Array(Symbol)] The default editing options.
|
|
31
40
|
def self.default_editing_translation_unit_options
|
|
32
41
|
bitmask = Lib.default_editing_translation_unit_options
|
|
33
42
|
Lib.opts_from Lib::TranslationUnitFlags, bitmask
|
|
34
43
|
end
|
|
35
|
-
|
|
44
|
+
|
|
45
|
+
# Get the default save options for this translation unit.
|
|
46
|
+
# @returns [Array(Symbol)] The default save options.
|
|
36
47
|
def default_save_options
|
|
37
48
|
bitmask = Lib.default_save_options(self)
|
|
38
49
|
Lib.opts_from Lib::SaveTranslationUnitFlags, bitmask
|
|
39
50
|
end
|
|
40
|
-
|
|
51
|
+
|
|
52
|
+
# Save the translation unit to a file.
|
|
53
|
+
# @parameter filename [String] The path where the translation unit should be saved.
|
|
54
|
+
# @parameter opts [Hash] Save options.
|
|
55
|
+
# @raises [Error] If saving fails.
|
|
41
56
|
def save(filename, opts = {})
|
|
42
57
|
ret = Lib.save_translation_unit(self, filename, 0)
|
|
43
58
|
sym = Lib::SaveError[ret]
|
|
44
59
|
raise Error, "unknown return values: #{ret} #{sym.inspect}" unless sym
|
|
45
60
|
raise Error, "save error: #{sym.inspect}, filename: #{filename}" if sym != :none
|
|
46
61
|
end
|
|
47
|
-
|
|
62
|
+
|
|
63
|
+
# Get the default reparse options for this translation unit.
|
|
64
|
+
# @returns [Array(Symbol)] The default reparse options.
|
|
48
65
|
def default_reparse_options
|
|
49
66
|
bitmask = Lib.default_save_options(self)
|
|
50
67
|
Lib.opts_from Lib::ReparseFlags, bitmask
|
|
51
68
|
end
|
|
52
|
-
|
|
69
|
+
|
|
70
|
+
# Reparse the translation unit with updated file contents.
|
|
71
|
+
# @parameter unsaved [Array(UnsavedFile)] Unsaved file buffers.
|
|
72
|
+
# @parameter opts [Hash] Reparse options.
|
|
73
|
+
# @raises [Error] If reparsing fails.
|
|
53
74
|
def reparse(unsaved = [], opts = {})
|
|
54
75
|
unsaved_files = UnsavedFile.unsaved_pointer_from(unsaved)
|
|
55
76
|
if Lib.reparse_translation_unit(self, unsaved.size, unsaved_files, 0) != 0
|
|
56
77
|
raise Error, "reparse error"
|
|
57
78
|
end
|
|
58
79
|
end
|
|
59
|
-
|
|
80
|
+
|
|
81
|
+
# Get all diagnostics for this translation unit.
|
|
82
|
+
# @returns [Array(Diagnostic)] Array of diagnostics.
|
|
60
83
|
def diagnostics
|
|
61
84
|
n = Lib.get_num_diagnostics(self)
|
|
62
|
-
|
|
85
|
+
|
|
63
86
|
n.times.map do |i|
|
|
64
87
|
Diagnostic.new(self, Lib.get_diagnostic(self, i))
|
|
65
88
|
end
|
|
66
89
|
end
|
|
67
|
-
|
|
90
|
+
|
|
91
|
+
# Get a cursor for the translation unit or at a specific location.
|
|
92
|
+
# @parameter location [SourceLocation | Nil] The location for the cursor, or `nil` for the root cursor.
|
|
93
|
+
# @returns [Cursor] The cursor at the specified location or the root cursor.
|
|
68
94
|
def cursor(location = nil)
|
|
69
95
|
if location.nil?
|
|
70
96
|
Cursor.new Lib.get_translation_unit_cursor(self), self
|
|
@@ -72,15 +98,27 @@ module FFI
|
|
|
72
98
|
Cursor.new Lib.get_cursor(self, location.location), self
|
|
73
99
|
end
|
|
74
100
|
end
|
|
75
|
-
|
|
101
|
+
|
|
102
|
+
# Get a source location by file, line, and column.
|
|
103
|
+
# @parameter file [File] The file object.
|
|
104
|
+
# @parameter line [Integer] The line number (1-indexed).
|
|
105
|
+
# @parameter column [Integer] The column number (1-indexed).
|
|
106
|
+
# @returns [ExpansionLocation] The source location.
|
|
76
107
|
def location(file, line, column)
|
|
77
108
|
ExpansionLocation.new Lib.get_location(self, file, line, column)
|
|
78
109
|
end
|
|
79
|
-
|
|
110
|
+
|
|
111
|
+
# Get a source location by file and byte offset.
|
|
112
|
+
# @parameter file [File] The file object.
|
|
113
|
+
# @parameter offset [Integer] The byte offset from the start of the file.
|
|
114
|
+
# @returns [ExpansionLocation] The source location.
|
|
80
115
|
def location_offset(file, offset)
|
|
81
116
|
ExpansionLocation.new Lib.get_location_offset(self, file, offset)
|
|
82
117
|
end
|
|
83
|
-
|
|
118
|
+
|
|
119
|
+
# Get a file object from this translation unit.
|
|
120
|
+
# @parameter file_name [String | Nil] The file name, or `nil` to get the main file.
|
|
121
|
+
# @returns [File] The file object.
|
|
84
122
|
def file(file_name = nil)
|
|
85
123
|
if file_name.nil?
|
|
86
124
|
File.new(Lib.get_file(self, spelling), self)
|
|
@@ -88,22 +126,36 @@ module FFI
|
|
|
88
126
|
File.new(Lib.get_file(self, file_name), self)
|
|
89
127
|
end
|
|
90
128
|
end
|
|
91
|
-
|
|
129
|
+
|
|
130
|
+
# Get the spelling (filename) of this translation unit.
|
|
131
|
+
# @returns [String] The filename of the translation unit.
|
|
92
132
|
def spelling
|
|
93
133
|
Lib.extract_string Lib.get_translation_unit_spelling(self)
|
|
94
134
|
end
|
|
95
|
-
|
|
135
|
+
|
|
136
|
+
# Get resource usage information for this translation unit.
|
|
137
|
+
# @returns [ResourceUsage] Resource usage statistics.
|
|
96
138
|
def resource_usage
|
|
97
139
|
FFI::Clang::TranslationUnit::ResourceUsage.new Lib.resource_usage(self)
|
|
98
140
|
end
|
|
99
|
-
|
|
141
|
+
|
|
142
|
+
# Tokenize a source range.
|
|
143
|
+
# @parameter range [SourceRange] The source range to tokenize.
|
|
144
|
+
# @returns [Tokens] Collection of tokens in the range.
|
|
100
145
|
def tokenize(range)
|
|
101
146
|
token_ptr = MemoryPointer.new :pointer
|
|
102
147
|
uint_ptr = MemoryPointer.new :uint
|
|
103
148
|
Lib.tokenize(self, range.range, token_ptr, uint_ptr)
|
|
104
149
|
Tokens.new(token_ptr.get_pointer(0), uint_ptr.get_uint(0), self)
|
|
105
150
|
end
|
|
106
|
-
|
|
151
|
+
|
|
152
|
+
# Perform code completion at a specific location.
|
|
153
|
+
# @parameter source_file [String] The path to the source file.
|
|
154
|
+
# @parameter line [Integer] The line number for code completion.
|
|
155
|
+
# @parameter column [Integer] The column number for code completion.
|
|
156
|
+
# @parameter unsaved [Array(UnsavedFile)] Unsaved file buffers.
|
|
157
|
+
# @parameter opts [Array(Symbol) | Nil] Code completion options, or `nil` for defaults.
|
|
158
|
+
# @returns [CodeCompletion::Results] The code completion results.
|
|
107
159
|
def code_complete(source_file, line, column, unsaved = [], opts = nil)
|
|
108
160
|
opts = CodeCompletion.default_code_completion_options if opts.nil?
|
|
109
161
|
unsaved_files = UnsavedFile.unsaved_pointer_from(unsaved)
|
|
@@ -111,23 +163,29 @@ module FFI
|
|
|
111
163
|
ptr = Lib.code_complete_at(self, source_file, line, column, unsaved_files, unsaved.length, option_bitmask)
|
|
112
164
|
CodeCompletion::Results.new ptr, self
|
|
113
165
|
end
|
|
114
|
-
|
|
166
|
+
|
|
167
|
+
# Iterate over all file inclusions in this translation unit.
|
|
168
|
+
# @yields {|file, locations| ...} Each inclusion with its file path and stack.
|
|
169
|
+
# @parameter file [String] The included file path.
|
|
170
|
+
# @parameter locations [Array(SourceLocation)] The inclusion stack.
|
|
115
171
|
def inclusions(&block)
|
|
116
172
|
adapter = Proc.new do |included_file, inclusion_stack, include_len, unused|
|
|
117
173
|
file = Lib.extract_string Lib.get_file_name(included_file)
|
|
118
174
|
cur_ptr = inclusion_stack
|
|
119
175
|
inclusions = []
|
|
120
|
-
include_len.times {
|
|
121
|
-
|
|
122
|
-
cur_ptr += Lib::CXSourceLocation.size
|
|
176
|
+
include_len.times {inclusions << SourceLocation.new(Lib::CXSourceLocation.new(cur_ptr))
|
|
177
|
+
cur_ptr += Lib::CXSourceLocation.size
|
|
123
178
|
}
|
|
124
179
|
block.call file, inclusions
|
|
125
180
|
end
|
|
126
181
|
|
|
127
182
|
Lib.get_inclusions(self, adapter, nil)
|
|
128
183
|
end
|
|
129
|
-
|
|
184
|
+
|
|
185
|
+
# Represents resource usage statistics for a translation unit.
|
|
130
186
|
class ResourceUsage < AutoPointer
|
|
187
|
+
# Initialize resource usage from a CXTUResourceUsage structure.
|
|
188
|
+
# @parameter resource_usage [Lib::CXTUResourceUsage] The resource usage structure.
|
|
131
189
|
def initialize(resource_usage)
|
|
132
190
|
# CXResourceUsage is returned by value and should be freed explicitly.
|
|
133
191
|
# Get FFI::pointer of the data so that the data is handled by AutoPointer.
|
|
@@ -135,22 +193,28 @@ module FFI
|
|
|
135
193
|
super(pointer)
|
|
136
194
|
@resource_usage = resource_usage
|
|
137
195
|
end
|
|
138
|
-
|
|
196
|
+
|
|
197
|
+
# Release the resource usage pointer.
|
|
198
|
+
# @parameter pointer [FFI::Pointer] The resource usage pointer to release.
|
|
139
199
|
def self.release(pointer)
|
|
140
200
|
# clang_disposeCXTUResourceUsage requires value type, so create it by pointer
|
|
141
201
|
Lib.dispose_resource_usage(Lib::CXTUResourceUsage.new(pointer))
|
|
142
202
|
end
|
|
143
|
-
|
|
203
|
+
|
|
204
|
+
# Get the name of a resource usage kind.
|
|
205
|
+
# @parameter kind [Symbol] The resource usage kind.
|
|
206
|
+
# @returns [String] The name of the resource kind.
|
|
144
207
|
def self.name(kind)
|
|
145
208
|
Lib.resource_usage_name(kind)
|
|
146
209
|
end
|
|
147
|
-
|
|
210
|
+
|
|
211
|
+
# Get all resource usage entries.
|
|
212
|
+
# @returns [Array(Lib::CXTUResourceUsageEntry)] The resource usage entries.
|
|
148
213
|
def entries
|
|
149
214
|
ary = []
|
|
150
215
|
ptr = @resource_usage[:entries]
|
|
151
|
-
@resource_usage[:numEntries].times {
|
|
152
|
-
|
|
153
|
-
ptr += Lib::CXTUResourceUsageEntry.size
|
|
216
|
+
@resource_usage[:numEntries].times {ary << Lib::CXTUResourceUsageEntry.new(ptr)
|
|
217
|
+
ptr += Lib::CXTUResourceUsageEntry.size
|
|
154
218
|
}
|
|
155
219
|
ary
|
|
156
220
|
end
|
|
@@ -1,11 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2024, by Charlie Savage.
|
|
5
|
+
# Copyright, 2025, by Samuel Williams.
|
|
6
|
+
|
|
1
7
|
module FFI
|
|
2
8
|
module Clang
|
|
9
|
+
# Type system classes for representing C/C++ types.
|
|
10
|
+
# @namespace
|
|
3
11
|
module Types
|
|
12
|
+
# Represents an array type.
|
|
13
|
+
# This includes constant arrays, incomplete arrays, variable arrays, and dependent-sized arrays.
|
|
4
14
|
class Array < Type
|
|
15
|
+
# Get the element type of this array.
|
|
16
|
+
# @returns [Type] The type of elements in this array.
|
|
5
17
|
def element_type
|
|
6
18
|
Type.create Lib.get_array_element_type(@type), @translation_unit
|
|
7
19
|
end
|
|
8
|
-
|
|
20
|
+
|
|
21
|
+
# Get the size of this array.
|
|
22
|
+
# @returns [Integer] The number of elements in the array, or -1 if the size is not available.
|
|
9
23
|
def size
|
|
10
24
|
Lib.get_array_size(@type)
|
|
11
25
|
end
|
|
@@ -1,26 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2024-2025, by Charlie Savage.
|
|
5
|
+
# Copyright, 2025, by Samuel Williams.
|
|
6
|
+
|
|
1
7
|
module FFI
|
|
2
8
|
module Clang
|
|
3
9
|
module Types
|
|
10
|
+
# Represents an elaborated type (e.g., struct, union, enum with an elaborated type specifier).
|
|
11
|
+
# Elaborated types may include type qualifiers and nested name specifiers.
|
|
4
12
|
class Elaborated < Type
|
|
13
|
+
# Get the named type that this elaborated type refers to.
|
|
14
|
+
# @returns [Type] The underlying named type.
|
|
5
15
|
def named_type
|
|
6
16
|
Type.create Lib.get_named_type(@type), @translation_unit
|
|
7
17
|
end
|
|
8
|
-
|
|
9
|
-
#
|
|
18
|
+
|
|
19
|
+
# Check if this is an anonymous elaborated type.
|
|
20
|
+
# Example anonymous union where `u` is an elaborated type:
|
|
10
21
|
#
|
|
11
22
|
# typedef struct {
|
|
12
23
|
# union {
|
|
13
24
|
# int idata;
|
|
14
25
|
# } u;
|
|
15
26
|
# } SomeStruct;
|
|
27
|
+
#
|
|
28
|
+
# @returns [Boolean] True if this elaborated type is anonymous.
|
|
16
29
|
def anonymous?
|
|
17
30
|
self.declaration.anonymous?
|
|
18
31
|
end
|
|
19
|
-
|
|
32
|
+
|
|
33
|
+
# Check if this elaborated type is a pointer in its canonical form.
|
|
34
|
+
# @returns [Boolean] True if the canonical type is a pointer.
|
|
20
35
|
def pointer?
|
|
21
36
|
self.canonical.is_a?(Pointer)
|
|
22
37
|
end
|
|
23
38
|
end
|
|
24
39
|
end
|
|
25
40
|
end
|
|
26
|
-
end
|
|
41
|
+
end
|
|
@@ -1,43 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2024, by Charlie Savage.
|
|
5
|
+
# Copyright, 2025, by Samuel Williams.
|
|
6
|
+
|
|
1
7
|
module FFI
|
|
2
8
|
module Clang
|
|
3
9
|
module Types
|
|
10
|
+
# Represents a function type.
|
|
11
|
+
# This includes functions with and without prototypes.
|
|
4
12
|
class Function < Type
|
|
5
13
|
include Enumerable
|
|
6
|
-
|
|
14
|
+
|
|
15
|
+
# Check if this function is variadic.
|
|
16
|
+
# @returns [Boolean] True if the function accepts a variable number of arguments.
|
|
7
17
|
def variadic?
|
|
8
18
|
Lib.is_function_type_variadic(@type) != 0
|
|
9
19
|
end
|
|
10
|
-
|
|
20
|
+
|
|
21
|
+
# Get the number of arguments this function takes.
|
|
22
|
+
# @returns [Integer] The number of arguments.
|
|
11
23
|
def args_size
|
|
12
24
|
Lib.get_num_arg_types(@type)
|
|
13
25
|
end
|
|
14
|
-
|
|
26
|
+
|
|
27
|
+
# Get the type of a specific argument.
|
|
28
|
+
# @parameter i [Integer] The zero-based argument index.
|
|
29
|
+
# @returns [Type] The type of the argument at the specified index.
|
|
15
30
|
def arg_type(i)
|
|
16
31
|
Type.create Lib.get_arg_type(@type, i), @translation_unit
|
|
17
32
|
end
|
|
18
|
-
|
|
33
|
+
|
|
34
|
+
# Iterate over all argument types or get an enumerator.
|
|
35
|
+
# @yields {|type| ...} Yields each argument type if a block is given.
|
|
36
|
+
# @parameter type [Type] An argument type.
|
|
37
|
+
# @returns [Enumerator, self] An enumerator if no block is given, self otherwise.
|
|
19
38
|
def arg_types
|
|
20
39
|
return to_enum(:arg_types) unless block_given?
|
|
21
|
-
|
|
40
|
+
|
|
22
41
|
self.args_size.times do |i|
|
|
23
42
|
yield self.arg_type(i)
|
|
24
43
|
end
|
|
25
|
-
|
|
44
|
+
|
|
26
45
|
self
|
|
27
46
|
end
|
|
28
|
-
|
|
47
|
+
|
|
48
|
+
# Get the return type of this function.
|
|
49
|
+
# @returns [Type] The function's return type.
|
|
29
50
|
def result_type
|
|
30
51
|
Type.create Lib.get_result_type(@type), @translation_unit
|
|
31
52
|
end
|
|
32
|
-
|
|
53
|
+
|
|
54
|
+
# Get the calling convention of this function.
|
|
55
|
+
# @returns [Symbol] The calling convention (e.g., :calling_conv_c, :calling_conv_x86_stdcall).
|
|
33
56
|
def calling_conv
|
|
34
57
|
Lib.get_fuction_type_calling_conv(@type)
|
|
35
58
|
end
|
|
36
|
-
|
|
59
|
+
|
|
60
|
+
# Get the exception specification type for this function.
|
|
61
|
+
# @returns [Symbol] The exception specification type (e.g., :exception_spec_none, :exception_spec_basic_noexcept).
|
|
37
62
|
def exception_specification
|
|
38
63
|
Lib.get_exception_specification_type(@type)
|
|
39
64
|
end
|
|
40
65
|
end
|
|
41
66
|
end
|
|
42
67
|
end
|
|
43
|
-
end
|
|
68
|
+
end
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2024, by Charlie Savage.
|
|
5
|
+
# Copyright, 2025, by Samuel Williams.
|
|
6
|
+
|
|
1
7
|
module FFI
|
|
2
8
|
module Clang
|
|
3
9
|
module Types
|
|
10
|
+
# Represents a pointer type.
|
|
11
|
+
# This includes regular pointers, block pointers, Objective-C object pointers, and member pointers.
|
|
4
12
|
class Pointer < Type
|
|
13
|
+
# Get the type that this pointer points to.
|
|
14
|
+
# @returns [Type] The pointee type.
|
|
5
15
|
def pointee
|
|
6
16
|
Type.create Lib.get_pointee_type(@type), @translation_unit
|
|
7
17
|
end
|
|
8
|
-
|
|
18
|
+
|
|
19
|
+
# Check if this is a function pointer.
|
|
20
|
+
# @returns [Boolean] True if this pointer points to a function.
|
|
9
21
|
def function?
|
|
10
22
|
self.pointee.is_a?(Types::Function)
|
|
11
23
|
end
|
|
12
|
-
|
|
24
|
+
|
|
25
|
+
# Get the class type for member pointers.
|
|
26
|
+
# @returns [Type, nil] The class type if this is a member pointer, nil otherwise.
|
|
13
27
|
def class_type
|
|
14
28
|
if self.kind == :type_member_pointer
|
|
15
29
|
Type.create Lib.type_get_class_type(@type), @translation_unit
|
|
@@ -17,16 +31,18 @@ module FFI
|
|
|
17
31
|
nil
|
|
18
32
|
end
|
|
19
33
|
end
|
|
20
|
-
|
|
34
|
+
|
|
35
|
+
# Check if this pointer references a forward declaration.
|
|
36
|
+
# @returns [Boolean] True if this pointer points to a forward-declared type.
|
|
21
37
|
def forward_declaration?
|
|
22
38
|
# Is this a pointer to a record (struct or union) that referenced
|
|
23
39
|
# a forward declaration at the point of its inclusion in the translation unit?
|
|
24
40
|
if !self.function? && self.pointee.is_a?(Types::Elaborated) &&
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
self.pointee.canonical.is_a?(Types::Record)
|
|
42
|
+
|
|
27
43
|
# Get the universal symbol reference
|
|
28
44
|
usr = self.pointee.canonical.declaration.usr
|
|
29
|
-
|
|
45
|
+
|
|
30
46
|
# Now does that same usr occur earlier in the file?
|
|
31
47
|
first_declaration, _ = self.translation_unit.cursor.find do |child, parent|
|
|
32
48
|
child.usr == usr
|
|
@@ -39,4 +55,4 @@ module FFI
|
|
|
39
55
|
end
|
|
40
56
|
end
|
|
41
57
|
end
|
|
42
|
-
end
|
|
58
|
+
end
|
|
@@ -1,23 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2024, by Charlie Savage.
|
|
5
|
+
# Copyright, 2025, by Samuel Williams.
|
|
6
|
+
|
|
1
7
|
module FFI
|
|
2
8
|
module Clang
|
|
3
9
|
module Types
|
|
10
|
+
# Represents a record type (struct or union).
|
|
4
11
|
class Record < Type
|
|
12
|
+
# Get the byte offset of a field within this record.
|
|
13
|
+
# @parameter field [String] The name of the field.
|
|
14
|
+
# @returns [Integer] The byte offset of the field, or -1 if not found.
|
|
5
15
|
def offsetof(field)
|
|
6
16
|
Lib.type_get_offset_of(@type, field)
|
|
7
17
|
end
|
|
8
|
-
|
|
18
|
+
|
|
19
|
+
# Check if this is an anonymous record.
|
|
20
|
+
# @returns [Boolean] True if this record is unnamed/anonymous.
|
|
9
21
|
def anonymous?
|
|
10
22
|
self.spelling.match(/unnamed/)
|
|
11
23
|
end
|
|
12
|
-
|
|
24
|
+
|
|
25
|
+
# Get the kind of record (struct or union).
|
|
26
|
+
# @returns [Symbol] Either :struct or :union.
|
|
27
|
+
# @raises [RuntimeError] If the record type cannot be determined.
|
|
13
28
|
def record_type
|
|
14
29
|
case self.spelling
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
30
|
+
when /struct/
|
|
31
|
+
:struct
|
|
32
|
+
when /union/
|
|
33
|
+
:union
|
|
34
|
+
else
|
|
35
|
+
raise("Unknown record type: #{self.spelling}")
|
|
21
36
|
end
|
|
22
37
|
end
|
|
23
38
|
end
|