ffi-clang 0.15.1 → 0.16.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/lib/ffi/clang/cursor.rb +55 -0
- data/lib/ffi/clang/types/type.rb +290 -3
- data/lib/ffi/clang/version.rb +1 -1
- data/readme.md +10 -12
- data/releases.md +10 -0
- data.tar.gz.sig +0 -0
- metadata +1 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1550a49c2829fb140990ff821a8681f1c6ab38587e167b408a6d7dccc8bee9df
|
|
4
|
+
data.tar.gz: 9ce46bcbba80c9f97bef6f5f3a444fb8608d280dc21c75410855088fdbc2eaec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 03053f8d75313265b8bfba38addd7b3ba5fcfc93f064136e79fd9b6c09a97c268b56eb02ad1716c352eade3121483d3c0b7d5b6caf6745f5f2e8cd2e72e74f3f
|
|
7
|
+
data.tar.gz: b987eb3c2ebfc91f946079b8ee0e64c8cf21181791393a934c7c6fdd3bfab0c4147afeda83198b52d85c1a07a69ed2e0d97a34bc5084d9f72a5b2057c05122bc
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/lib/ffi/clang/cursor.rb
CHANGED
|
@@ -813,6 +813,61 @@ module FFI
|
|
|
813
813
|
Lib.is_abstract(@cursor) != 0
|
|
814
814
|
end
|
|
815
815
|
|
|
816
|
+
# Check if this class/struct is copyable: it has no inaccessible
|
|
817
|
+
# (deleted, private, or protected) copy constructor, and every base
|
|
818
|
+
# class is copyable (recursively). Returns true on cursors that
|
|
819
|
+
# don't denote a class/struct, since the question doesn't apply.
|
|
820
|
+
#
|
|
821
|
+
# A class with no explicit copy constructor is treated as copyable —
|
|
822
|
+
# the implicit one is generated. We only flag explicit `= delete` or
|
|
823
|
+
# private/protected access.
|
|
824
|
+
#
|
|
825
|
+
# @returns [Boolean] True if instances of this type can be copied.
|
|
826
|
+
def copyable?
|
|
827
|
+
return true unless [:cursor_class_decl, :cursor_struct].include?(self.kind)
|
|
828
|
+
|
|
829
|
+
copy_constructors = self.find_by_kind(false, :cursor_constructor).select(&:copy_constructor?)
|
|
830
|
+
copy_constructors.each do |constructor|
|
|
831
|
+
return false if constructor.deleted? || constructor.private? || constructor.protected?
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
self.find_by_kind(false, :cursor_cxx_base_specifier).each do |base|
|
|
835
|
+
base_decl = base.type.declaration
|
|
836
|
+
next if base_decl.kind == :cursor_no_decl_found
|
|
837
|
+
return false unless base_decl.copyable?
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
true
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
# Check if this class/struct is copy-assignable: it has no
|
|
844
|
+
# inaccessible (deleted, private, or protected) copy assignment
|
|
845
|
+
# operator, and every base class is copy-assignable (recursively).
|
|
846
|
+
# Returns true on cursors that don't denote a class/struct, since
|
|
847
|
+
# the question doesn't apply.
|
|
848
|
+
#
|
|
849
|
+
# A class with no explicit copy assignment operator is treated as
|
|
850
|
+
# copy-assignable — the implicit one is generated. We only flag
|
|
851
|
+
# explicit `= delete` or private/protected access.
|
|
852
|
+
#
|
|
853
|
+
# @returns [Boolean] True if instances of this type can be copy-assigned.
|
|
854
|
+
def copy_assignable?
|
|
855
|
+
return true unless [:cursor_class_decl, :cursor_struct].include?(self.kind)
|
|
856
|
+
|
|
857
|
+
copy_assignment_operators = self.find_by_kind(false, :cursor_cxx_method).select(&:copy_assignment_operator?)
|
|
858
|
+
copy_assignment_operators.each do |operator|
|
|
859
|
+
return false if operator.deleted? || operator.private? || operator.protected?
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
self.find_by_kind(false, :cursor_cxx_base_specifier).each do |base|
|
|
863
|
+
base_decl = base.type.declaration
|
|
864
|
+
next if base_decl.kind == :cursor_no_decl_found
|
|
865
|
+
return false unless base_decl.copy_assignable?
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
true
|
|
869
|
+
end
|
|
870
|
+
|
|
816
871
|
# Check if this is a scoped enum.
|
|
817
872
|
# @returns [Boolean] True if it's a scoped enum.
|
|
818
873
|
def enum_scoped?
|
data/lib/ffi/clang/types/type.rb
CHANGED
|
@@ -127,17 +127,79 @@ module FFI
|
|
|
127
127
|
|
|
128
128
|
# Get the type with all qualifiers (const, volatile, restrict) removed.
|
|
129
129
|
# @returns [Type] The unqualified type.
|
|
130
|
+
#
|
|
131
|
+
# Guards against :type_invalid input: clang_getUnqualifiedType has
|
|
132
|
+
# no null check on the underlying QualType (unlike its siblings
|
|
133
|
+
# clang_getNonReferenceType / clang_getCanonicalType / etc.) and
|
|
134
|
+
# segfaults on invalid types. Returning self preserves the
|
|
135
|
+
# invalid kind without entering libclang.
|
|
130
136
|
def unqualified_type
|
|
137
|
+
return self if self.kind == :type_invalid
|
|
131
138
|
Type.create Lib.get_unqualified_type(@type), @translation_unit
|
|
132
139
|
end
|
|
133
140
|
|
|
141
|
+
# True if this type is an lvalue or rvalue reference.
|
|
142
|
+
# @returns [Boolean] Whether this type is `T &` or `T &&`.
|
|
143
|
+
def reference?
|
|
144
|
+
self.kind == :type_lvalue_ref || self.kind == :type_rvalue_ref
|
|
145
|
+
end
|
|
146
|
+
|
|
134
147
|
# Get the non-reference type.
|
|
135
148
|
# For reference types, returns the type that is being referenced.
|
|
136
149
|
# @returns [Type] The non-reference type.
|
|
150
|
+
#
|
|
151
|
+
# Guards against :type_invalid input: clang_getNonReferenceType
|
|
152
|
+
# dereferences the underlying QualType without a null check and
|
|
153
|
+
# segfaults on invalid types. Returning self preserves the
|
|
154
|
+
# invalid kind without entering libclang.
|
|
137
155
|
def non_reference_type
|
|
156
|
+
return self if self.kind == :type_invalid
|
|
138
157
|
Type.create Lib.get_non_reference_type(@type), @translation_unit
|
|
139
158
|
end
|
|
140
159
|
|
|
160
|
+
# Get the intrinsic type — strip the reference, follow pointer
|
|
161
|
+
# indirection until reaching a non-pointer type, then drop
|
|
162
|
+
# cv-qualifiers. Named after Rice's `intrinsic_type` metafunction
|
|
163
|
+
# of the same shape. Useful when asking "what does this type
|
|
164
|
+
# ultimately denote?" for skip-list and bindability checks.
|
|
165
|
+
#
|
|
166
|
+
# Examples:
|
|
167
|
+
# * `T &` becomes `T`
|
|
168
|
+
# * `T *` becomes `T`
|
|
169
|
+
# * `T **&` becomes `T`
|
|
170
|
+
# * `const T &` becomes `T`
|
|
171
|
+
#
|
|
172
|
+
# @returns [Type] The intrinsic (innermost, unqualified) type.
|
|
173
|
+
def intrinsic_type
|
|
174
|
+
type = self.non_reference_type
|
|
175
|
+
while type.kind == :type_pointer
|
|
176
|
+
type = type.pointee
|
|
177
|
+
end
|
|
178
|
+
type.unqualified_type
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Check if this type's declaration (after reference stripping)
|
|
182
|
+
# has an accessible copy constructor and copyable bases.
|
|
183
|
+
# Returns true for non-class types (fundamentals, pointers,
|
|
184
|
+
# enums) and for types whose declaration is unavailable
|
|
185
|
+
# (:cursor_no_decl_found).
|
|
186
|
+
#
|
|
187
|
+
# @returns [Boolean] True if instances of this type can be copied.
|
|
188
|
+
def copyable?
|
|
189
|
+
self.non_reference_type.declaration.copyable?
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Check if this type's declaration (after reference stripping)
|
|
193
|
+
# has an accessible copy assignment operator and copy-assignable
|
|
194
|
+
# bases. Returns true for non-class types (fundamentals, pointers,
|
|
195
|
+
# enums) and for types whose declaration is unavailable
|
|
196
|
+
# (:cursor_no_decl_found).
|
|
197
|
+
#
|
|
198
|
+
# @returns [Boolean] True if instances of this type can be copy-assigned.
|
|
199
|
+
def copy_assignable?
|
|
200
|
+
self.non_reference_type.declaration.copy_assignable?
|
|
201
|
+
end
|
|
202
|
+
|
|
141
203
|
# Get the type of a template argument at the given index.
|
|
142
204
|
# For template specializations (e.g., `std::vector<int>`), this returns the type of
|
|
143
205
|
# the template argument at the specified position.
|
|
@@ -199,11 +261,236 @@ module FFI
|
|
|
199
261
|
end
|
|
200
262
|
|
|
201
263
|
# Get the fully qualified name of this type.
|
|
202
|
-
#
|
|
264
|
+
#
|
|
265
|
+
# On libclang 21+ this dispatches to clang_getFullyQualifiedName.
|
|
266
|
+
# On earlier libclang versions it falls back to a Ruby shim that
|
|
267
|
+
# composes existing libclang APIs (declaration, qualified_name,
|
|
268
|
+
# template arguments, pointer/array/reference unwrapping, etc.).
|
|
269
|
+
#
|
|
270
|
+
# Known shim limitation: STL container typedefs that depend on
|
|
271
|
+
# default template arguments (e.g., `std::vector<T>::iterator`)
|
|
272
|
+
# don't expand the defaults. Output is valid C++ and matches
|
|
273
|
+
# the native result for non-STL types.
|
|
274
|
+
#
|
|
275
|
+
# @parameter policy [PrintingPolicy] The printing policy to use. Ignored by the shim.
|
|
203
276
|
# @parameter with_global_ns_prefix [Boolean] Whether to prepend "::".
|
|
204
277
|
# @returns [String] The fully qualified type name.
|
|
205
|
-
def fully_qualified_name(policy, with_global_ns_prefix: false)
|
|
206
|
-
|
|
278
|
+
def fully_qualified_name(policy = nil, with_global_ns_prefix: false)
|
|
279
|
+
if Lib.respond_to?(:get_fully_qualified_name)
|
|
280
|
+
Lib.extract_string Lib.get_fully_qualified_name(@type, policy, with_global_ns_prefix ? 1 : 0)
|
|
281
|
+
else
|
|
282
|
+
result = fqn_impl(policy)
|
|
283
|
+
with_global_ns_prefix ? "::#{result}" : result
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Shim implementation of fully_qualified_name. Recursively walks the
|
|
288
|
+
# type tree, dispatching by kind. Public so it can be invoked across
|
|
289
|
+
# Type subclass boundaries during recursion.
|
|
290
|
+
# @parameter policy [PrintingPolicy] Threaded for native API parity; ignored.
|
|
291
|
+
# @returns [String] The fully qualified type spelling.
|
|
292
|
+
def fqn_impl(policy)
|
|
293
|
+
case self.kind
|
|
294
|
+
when :type_lvalue_ref
|
|
295
|
+
"#{self.non_reference_type.fqn_impl(policy)} &"
|
|
296
|
+
when :type_rvalue_ref
|
|
297
|
+
"#{self.non_reference_type.fqn_impl(policy)} &&"
|
|
298
|
+
when :type_pointer
|
|
299
|
+
fqn_pointer(policy)
|
|
300
|
+
when :type_constant_array
|
|
301
|
+
"#{self.element_type.fqn_impl(policy)}[#{self.size}]"
|
|
302
|
+
when :type_incomplete_array
|
|
303
|
+
"#{self.element_type.fqn_impl(policy)}[]"
|
|
304
|
+
when :type_elaborated
|
|
305
|
+
fqn_elaborated(policy)
|
|
306
|
+
when :type_record
|
|
307
|
+
fqn_record
|
|
308
|
+
else
|
|
309
|
+
self.spelling
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Spell a pointer type and its qualifier chain. Function pointers
|
|
314
|
+
# get a single rendering with parameter list; data pointers walk
|
|
315
|
+
# the chain collecting `*`/`*const` parts and qualify the leaf
|
|
316
|
+
# child once. Output matches native fqn: `int **`, `const char *const`, etc.
|
|
317
|
+
# @parameter policy [PrintingPolicy] Threaded to recursive fqn_impl calls.
|
|
318
|
+
# @returns [String] The fully qualified pointer type spelling.
|
|
319
|
+
def fqn_pointer(policy)
|
|
320
|
+
pointee = self.pointee
|
|
321
|
+
|
|
322
|
+
if [:type_function_proto, :type_function_no_proto].include?(pointee.kind)
|
|
323
|
+
ptr_const = self.const_qualified? ? " const" : ""
|
|
324
|
+
result_type = pointee.result_type.fqn_impl(policy)
|
|
325
|
+
arg_types = pointee.arg_types.map{|arg_type| arg_type.fqn_impl(policy)}.join(", ")
|
|
326
|
+
return "#{result_type} (*#{ptr_const})(#{arg_types})"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
parts = []
|
|
330
|
+
current = self
|
|
331
|
+
while current.kind == :type_pointer
|
|
332
|
+
inner = current.pointee
|
|
333
|
+
break if [:type_function_proto, :type_function_no_proto].include?(inner.kind)
|
|
334
|
+
|
|
335
|
+
parts << (current.const_qualified? ? "*const" : "*")
|
|
336
|
+
current = inner
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
"#{current.fqn_impl(policy)} #{parts.reverse.join}"
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Spell an elaborated type (typedef / type alias / enum / class)
|
|
343
|
+
# preserving the alias name where appropriate and qualifying
|
|
344
|
+
# template arguments recursively.
|
|
345
|
+
# @parameter policy [PrintingPolicy] Threaded to recursive calls.
|
|
346
|
+
# @returns [String] The fully qualified elaborated type spelling.
|
|
347
|
+
def fqn_elaborated(policy)
|
|
348
|
+
decl = self.declaration
|
|
349
|
+
const_prefix = self.const_qualified? ? "const " : ""
|
|
350
|
+
|
|
351
|
+
case decl.kind
|
|
352
|
+
when :cursor_typedef_decl, :cursor_type_alias_decl
|
|
353
|
+
# Preserve the typedef/alias name and qualify with namespace.
|
|
354
|
+
spelling = self.unqualified_type.spelling
|
|
355
|
+
qualified = decl.qualified_name
|
|
356
|
+
|
|
357
|
+
if spelling.include?("::")
|
|
358
|
+
# Already partially qualified. For nested typedefs in
|
|
359
|
+
# template classes (e.g., std::vector<Pixel>::iterator),
|
|
360
|
+
# qualify template args using the parent type's fqn.
|
|
361
|
+
parent = decl.semantic_parent
|
|
362
|
+
if parent.kind == :cursor_class_decl || parent.kind == :cursor_struct
|
|
363
|
+
parent_type = parent.type
|
|
364
|
+
parent_fqn = parent_type.fqn_impl(policy)
|
|
365
|
+
member_name = decl.spelling
|
|
366
|
+
"#{const_prefix}#{parent_fqn}::#{member_name}"
|
|
367
|
+
else
|
|
368
|
+
"#{const_prefix}#{spelling}"
|
|
369
|
+
end
|
|
370
|
+
elsif qualified
|
|
371
|
+
"#{const_prefix}#{qualified}"
|
|
372
|
+
else
|
|
373
|
+
"#{const_prefix}#{spelling}"
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
when :cursor_enum_decl
|
|
377
|
+
"#{const_prefix}#{decl.qualified_name}"
|
|
378
|
+
|
|
379
|
+
else
|
|
380
|
+
# Alias-template detection: e.g. `AliasOptional<int>` -> `Optional<int>`.
|
|
381
|
+
# The elaborated spelling preserves the alias; fqn_record
|
|
382
|
+
# would resolve to the underlying type. Use spelling when
|
|
383
|
+
# it's already qualified.
|
|
384
|
+
unqual = self.unqualified_type.spelling
|
|
385
|
+
if unqual.include?("::") && decl.spelling != unqual.sub(/<.*/, "").split("::").last
|
|
386
|
+
"#{const_prefix}#{unqual}"
|
|
387
|
+
else
|
|
388
|
+
base = fqn_record
|
|
389
|
+
if self.const_qualified? && !base.start_with?("const ")
|
|
390
|
+
"const #{base}"
|
|
391
|
+
else
|
|
392
|
+
base
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
# Spell a record type (class/struct) using its declaration's
|
|
399
|
+
# type spelling, which suppresses inline namespaces and includes
|
|
400
|
+
# template args. Falls back to qualified_name + spelling args
|
|
401
|
+
# for dependent types.
|
|
402
|
+
# @returns [String] The fully qualified record type spelling.
|
|
403
|
+
def fqn_record
|
|
404
|
+
decl = self.declaration
|
|
405
|
+
return self.spelling if decl.kind == :cursor_no_decl_found
|
|
406
|
+
|
|
407
|
+
const_prefix = self.const_qualified? ? "const " : ""
|
|
408
|
+
|
|
409
|
+
# decl.type.spelling gives the right qualification (no inline
|
|
410
|
+
# ns, with template args).
|
|
411
|
+
decl_spelling = decl.type.spelling
|
|
412
|
+
if decl_spelling && !decl_spelling.empty? && decl_spelling.include?("::")
|
|
413
|
+
# For concrete template types, recursively qualify args.
|
|
414
|
+
n = self.num_template_arguments
|
|
415
|
+
if n > 0
|
|
416
|
+
base = decl_spelling.sub(/<.*/, "")
|
|
417
|
+
template_args = fqn_template_args(nil)
|
|
418
|
+
"#{const_prefix}#{base}#{template_args}"
|
|
419
|
+
else
|
|
420
|
+
"#{const_prefix}#{decl_spelling}"
|
|
421
|
+
end
|
|
422
|
+
else
|
|
423
|
+
# Fallback for types where decl.type.spelling is unqualified.
|
|
424
|
+
qualified = decl.qualified_name
|
|
425
|
+
bare_spelling = self.unqualified_type.spelling
|
|
426
|
+
template_args = bare_spelling.include?("<") ? bare_spelling[/<.*/] : ""
|
|
427
|
+
"#{const_prefix}#{qualified}#{template_args}"
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
# Build the qualified template argument list by recursing into
|
|
432
|
+
# each type argument. Non-type template parameters (e.g.
|
|
433
|
+
# integral values) are recovered from the type's spelling.
|
|
434
|
+
# @parameter policy [PrintingPolicy] Threaded to recursive calls.
|
|
435
|
+
# @returns [String] The bracketed argument list, including angle brackets, or empty.
|
|
436
|
+
def fqn_template_args(policy)
|
|
437
|
+
n = self.num_template_arguments
|
|
438
|
+
return "" unless n > 0
|
|
439
|
+
|
|
440
|
+
# Extract original args from spelling for non-type template params.
|
|
441
|
+
spelling_args = parse_template_args_from_spelling
|
|
442
|
+
|
|
443
|
+
args = (0...n).map do |i|
|
|
444
|
+
arg_type = self.template_argument_type(i)
|
|
445
|
+
if arg_type.kind == :type_invalid
|
|
446
|
+
# Non-type template arg (e.g., int N=3) — use from spelling.
|
|
447
|
+
spelling_args ? spelling_args[i] : nil
|
|
448
|
+
else
|
|
449
|
+
arg_type.fqn_impl(policy)
|
|
450
|
+
end
|
|
451
|
+
end.compact
|
|
452
|
+
|
|
453
|
+
return "" if args.empty?
|
|
454
|
+
"<#{args.join(", ")}>"
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
# Parse template arguments from the type's unqualified spelling,
|
|
458
|
+
# respecting nested angle brackets. Used to recover non-type
|
|
459
|
+
# template arguments that libclang surfaces only as text.
|
|
460
|
+
# @returns [Array(String) | nil] The argument substrings, or nil if no `<` was found.
|
|
461
|
+
def parse_template_args_from_spelling
|
|
462
|
+
bare = self.unqualified_type.spelling
|
|
463
|
+
start = bare.index("<")
|
|
464
|
+
return nil unless start
|
|
465
|
+
|
|
466
|
+
depth = 0
|
|
467
|
+
args = []
|
|
468
|
+
current = +""
|
|
469
|
+
bare[start + 1..].each_char do |c|
|
|
470
|
+
case c
|
|
471
|
+
when "<"
|
|
472
|
+
depth += 1
|
|
473
|
+
current << c
|
|
474
|
+
when ">"
|
|
475
|
+
if depth == 0
|
|
476
|
+
args << current.strip unless current.strip.empty?
|
|
477
|
+
break
|
|
478
|
+
else
|
|
479
|
+
depth -= 1
|
|
480
|
+
current << c
|
|
481
|
+
end
|
|
482
|
+
when ","
|
|
483
|
+
if depth == 0
|
|
484
|
+
args << current.strip
|
|
485
|
+
current = +""
|
|
486
|
+
else
|
|
487
|
+
current << c
|
|
488
|
+
end
|
|
489
|
+
else
|
|
490
|
+
current << c
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
args
|
|
207
494
|
end
|
|
208
495
|
|
|
209
496
|
# Visit all base classes of a C++ record type.
|
data/lib/ffi/clang/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -41,6 +41,16 @@ For example, to use a specific LLVM installation:
|
|
|
41
41
|
|
|
42
42
|
Please see the [project releases](https://socketry.github.io/ffi-clang/releases/index) for all releases.
|
|
43
43
|
|
|
44
|
+
### v0.16.0
|
|
45
|
+
|
|
46
|
+
- Add <code class="language-ruby">FFI::Clang::Types::Type\#intrinsic\_type</code>, which strips references and follows pointer indirection until reaching a non-pointer type and then drops cv-qualifiers.
|
|
47
|
+
- Add <code class="language-ruby">FFI::Clang::Types::Type\#reference?</code>, a one-liner predicate over `:type_lvalue_ref` and `:type_rvalue_ref`.
|
|
48
|
+
- Add <code class="language-ruby">FFI::Clang::Cursor\#copyable?</code> and <code class="language-ruby">FFI::Clang::Types::Type\#copyable?</code>, predicates that return true when a class/struct has an accessible copy constructor (none deleted, private, or protected) and every base class is copyable.
|
|
49
|
+
- Add <code class="language-ruby">FFI::Clang::Cursor\#copy\_assignable?</code> and <code class="language-ruby">FFI::Clang::Types::Type\#copy\_assignable?</code>, predicates that return true when a class/struct has an accessible copy assignment operator (none deleted, private, or protected) and every base class is copy-assignable.
|
|
50
|
+
- <code class="language-ruby">FFI::Clang::Types::Type\#fully\_qualified\_name</code> now works on libclang versions earlier than 21 via a Ruby shim that composes existing libclang APIs (declaration, qualified\_name, template arguments, pointer/array/reference unwrapping).
|
|
51
|
+
- Guard <code class="language-ruby">FFI::Clang::Types::Type\#unqualified\_type</code> against `:type_invalid` input.
|
|
52
|
+
- Guard <code class="language-ruby">FFI::Clang::Types::Type\#non\_reference\_type</code> against `:type_invalid` input.
|
|
53
|
+
|
|
44
54
|
### v0.15.1
|
|
45
55
|
|
|
46
56
|
- Use `-isystem` instead of `-I` for auto-discovered MSVC system include paths so that `in_system_header?` correctly identifies system headers.
|
|
@@ -101,18 +111,6 @@ Please see the [project releases](https://socketry.github.io/ffi-clang/releases/
|
|
|
101
111
|
- Set `cursor_translation_unit` enum value based on the Clang version. (\#64)
|
|
102
112
|
- Add various C++ introspection methods. (\#66)
|
|
103
113
|
|
|
104
|
-
### v0.7.0
|
|
105
|
-
|
|
106
|
-
- Fix incorrect return type of `clang_getTranslationUnitSpelling`.
|
|
107
|
-
- Fix `compilation_database_spec`.
|
|
108
|
-
- Fix libclang lookup for Xcode.
|
|
109
|
-
- Fix warning on class re-definition.
|
|
110
|
-
- Update cursor kinds.
|
|
111
|
-
- Find `libclang.dll` under Windows.
|
|
112
|
-
- Allow retrieval of list of references from a Cursor.
|
|
113
|
-
- Implement libclang `findReferencesInFile` functionality.
|
|
114
|
-
- Allow `TranslationUnit#file` to return the main file.
|
|
115
|
-
|
|
116
114
|
## Contributing
|
|
117
115
|
|
|
118
116
|
We welcome contributions to this project.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.16.0
|
|
4
|
+
|
|
5
|
+
- Add {ruby FFI::Clang::Types::Type\#intrinsic\_type}, which strips references and follows pointer indirection until reaching a non-pointer type and then drops cv-qualifiers.
|
|
6
|
+
- Add {ruby FFI::Clang::Types::Type\#reference?}, a one-liner predicate over `:type_lvalue_ref` and `:type_rvalue_ref`.
|
|
7
|
+
- Add {ruby FFI::Clang::Cursor\#copyable?} and {ruby FFI::Clang::Types::Type\#copyable?}, predicates that return true when a class/struct has an accessible copy constructor (none deleted, private, or protected) and every base class is copyable.
|
|
8
|
+
- Add {ruby FFI::Clang::Cursor\#copy\_assignable?} and {ruby FFI::Clang::Types::Type\#copy\_assignable?}, predicates that return true when a class/struct has an accessible copy assignment operator (none deleted, private, or protected) and every base class is copy-assignable.
|
|
9
|
+
- {ruby FFI::Clang::Types::Type\#fully\_qualified\_name} now works on libclang versions earlier than 21 via a Ruby shim that composes existing libclang APIs (declaration, qualified\_name, template arguments, pointer/array/reference unwrapping).
|
|
10
|
+
- Guard {ruby FFI::Clang::Types::Type\#unqualified\_type} against `:type_invalid` input.
|
|
11
|
+
- Guard {ruby FFI::Clang::Types::Type\#non\_reference\_type} against `:type_invalid` input.
|
|
12
|
+
|
|
3
13
|
## v0.15.1
|
|
4
14
|
|
|
5
15
|
- Use `-isystem` instead of `-I` for auto-discovered MSVC system include paths so that `in_system_header?` correctly identifies system headers.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
metadata.gz.sig
CHANGED
|
Binary file
|