kylemayes / clang-rs Goto Github PK
View Code? Open in Web Editor NEWA somewhat idiomatic Rust wrapper for libclang.
License: Apache License 2.0
A somewhat idiomatic Rust wrapper for libclang.
License: Apache License 2.0
I expected these two methods should be equivalent
Hey, thanks a lot for making this library, it's great!
When you get around to releasing a new version, may I suggest the following?
get_
prefix, which is generally discouraged in Rust (source); so instead of e.g. get_name()
, just use name()
.Entity
struct to Cursor
, to match the original bindings, or at least document it.Of course, if there's reasons for not doing these, then by all means do so, just wanted to note the few gripes I had.
This is blocking adoption of clang_sys
1.0 across the broader ecosystem. In particular in opencv-rs
, twistedfall/opencv-rust#159
The CXCursor_TranslationUnit change value in LLVM 15 from 300 to 350 (see this commit).
The clang::EntityKind::TranslationUnit
value is then wrong and a translation unit entity kind become NotImplemented
.
Hey Kyle!
I was just trying out clang-rs and the results I'm seeing from a trivial tokenization are pretty wonky. I'll share with you the simplest cases I've managed to pinpoint and hopefully you can shed some light on what's going on.
NOTE: I've tested both of these with clang_7_0
and clang_10_0
. Both show the same results.
The first issue I was seeing was with partial token results. Note that the last expression in the C source is f.a = 0;
, but note that the last token in the annotated token list is just f
with no children. The normal tokens look just fine and include identifiers for f
and a
in the assignment.
typedef struct
{
char *a;
} foo;
int main()
{
foo f;
f.a = 0;
}
extern crate clang;
fn main() {
let clang = clang::Clang::new().unwrap();
let index = clang::Index::new(&clang, false, false);
let translation_unit = index
.parser("test/simple.c")
.detailed_preprocessing_record(true)
.parse()
.expect("failed to parse");
println!("tu: {:#?}", translation_unit);
let diags = translation_unit.get_diagnostics();
println!("diags: {:?}", diags);
let tokens = translation_unit
.get_entity()
.get_range()
.unwrap()
.tokenize();
println!("tokens: {:#?}", tokens);
let annotated_tokens = translation_unit.annotate(&tokens);
println!("annotated: {:#?}", annotated_tokens);
println!(
"children: {:#?}",
annotated_tokens
.iter()
.map(|&t| t.map(|t| t.get_children()))
);
}
tu: TranslationUnit {
spelling: "test/simple.c",
}
diags: []
tokens: [
Token {
kind: Keyword,
spelling: "typedef",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 1,
offset: 0,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 8,
offset: 7,
},
},
},
Token {
kind: Keyword,
spelling: "struct",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 9,
offset: 8,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 15,
offset: 14,
},
},
},
Token {
kind: Punctuation,
spelling: "{",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 2,
column: 1,
offset: 15,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 2,
column: 2,
offset: 16,
},
},
},
Token {
kind: Keyword,
spelling: "char",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 3,
offset: 19,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 7,
offset: 23,
},
},
},
Token {
kind: Punctuation,
spelling: "*",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 8,
offset: 24,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 9,
offset: 25,
},
},
},
Token {
kind: Identifier,
spelling: "a",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 9,
offset: 25,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 10,
offset: 26,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 10,
offset: 26,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 11,
offset: 27,
},
},
},
Token {
kind: Punctuation,
spelling: "}",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 1,
offset: 28,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 2,
offset: 29,
},
},
},
Token {
kind: Identifier,
spelling: "foo",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 3,
offset: 30,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 6,
offset: 33,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 6,
offset: 33,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 7,
offset: 34,
},
},
},
Token {
kind: Keyword,
spelling: "int",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 1,
offset: 36,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 4,
offset: 39,
},
},
},
Token {
kind: Identifier,
spelling: "main",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 5,
offset: 40,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 9,
offset: 44,
},
},
},
Token {
kind: Punctuation,
spelling: "(",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 9,
offset: 44,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 10,
offset: 45,
},
},
},
Token {
kind: Punctuation,
spelling: ")",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 10,
offset: 45,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 11,
offset: 46,
},
},
},
Token {
kind: Punctuation,
spelling: "{",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 7,
column: 1,
offset: 47,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 7,
column: 2,
offset: 48,
},
},
},
Token {
kind: Identifier,
spelling: "foo",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 3,
offset: 51,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 6,
offset: 54,
},
},
},
Token {
kind: Identifier,
spelling: "f",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 7,
offset: 55,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 8,
offset: 56,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 8,
offset: 56,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 9,
offset: 57,
},
},
},
Token {
kind: Identifier,
spelling: "f",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 3,
offset: 60,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 4,
offset: 61,
},
},
},
Token {
kind: Punctuation,
spelling: ".",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 4,
offset: 61,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 5,
offset: 62,
},
},
},
Token {
kind: Identifier,
spelling: "a",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 5,
offset: 62,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 6,
offset: 63,
},
},
},
Token {
kind: Punctuation,
spelling: "=",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 7,
offset: 64,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 8,
offset: 65,
},
},
},
Token {
kind: Literal,
spelling: "0",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 9,
offset: 66,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 10,
offset: 67,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 10,
offset: 67,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 11,
offset: 68,
},
},
},
Token {
kind: Punctuation,
spelling: "}",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 10,
column: 1,
offset: 69,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 10,
column: 2,
offset: 70,
},
},
},
]
annotated: [
Some(
Entity {
kind: TypedefDecl,
display_name: Some(
"foo",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 3,
offset: 30,
},
),
},
),
Some(
Entity {
kind: TypedefDecl,
display_name: Some(
"foo",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 3,
offset: 30,
},
),
},
),
None,
None,
Some(
Entity {
kind: FieldDecl,
display_name: Some(
"a",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 9,
offset: 25,
},
),
},
),
None,
None,
None,
Some(
Entity {
kind: StructDecl,
display_name: None,
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 9,
offset: 8,
},
),
},
),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some(
Entity {
kind: TypeRef,
display_name: Some(
"foo",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 3,
offset: 51,
},
),
},
),
None,
None,
Some(
Entity {
kind: CompoundStmt,
display_name: None,
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 7,
column: 1,
offset: 47,
},
),
},
),
Some(
Entity {
kind: DeclRefExpr,
display_name: Some(
"f",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 3,
offset: 60,
},
),
},
),
]
children: Map {
iter: Iter(
[
Some(
Entity {
kind: TypedefDecl,
display_name: Some(
"foo",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 3,
offset: 30,
},
),
},
),
Some(
Entity {
kind: TypedefDecl,
display_name: Some(
"foo",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 3,
offset: 30,
},
),
},
),
None,
None,
Some(
Entity {
kind: FieldDecl,
display_name: Some(
"a",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 9,
offset: 25,
},
),
},
),
None,
None,
None,
Some(
Entity {
kind: StructDecl,
display_name: None,
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 9,
offset: 8,
},
),
},
),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some(
Entity {
kind: TypeRef,
display_name: Some(
"foo",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 3,
offset: 51,
},
),
},
),
None,
None,
Some(
Entity {
kind: CompoundStmt,
display_name: None,
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 7,
column: 1,
offset: 47,
},
),
},
),
Some(
Entity {
kind: DeclRefExpr,
display_name: Some(
"f",
),
location: Some(
SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 3,
offset: 60,
},
),
},
),
],
),
}
The second crazy issue showed up when I made a simple change to the C file: I made the char *a;
member an integer instead. Now there are no diagnostics, but also no annotated tokens at all. The normal tokens look just fine and include identifiers for f
and a
in the assignment.
typedef struct
{
int a;
} foo;
int main()
{
foo f;
f.a = 0;
}
Unchanged
tu: TranslationUnit {
spelling: "test/simple.c",
}
diags: []
tokens: [
Token {
kind: Keyword,
spelling: "typedef",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 1,
offset: 0,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 8,
offset: 7,
},
},
},
Token {
kind: Keyword,
spelling: "struct",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 9,
offset: 8,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 1,
column: 15,
offset: 14,
},
},
},
Token {
kind: Punctuation,
spelling: "{",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 2,
column: 1,
offset: 15,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 2,
column: 2,
offset: 16,
},
},
},
Token {
kind: Keyword,
spelling: "int",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 3,
offset: 19,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 6,
offset: 22,
},
},
},
Token {
kind: Identifier,
spelling: "a",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 7,
offset: 23,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 8,
offset: 24,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 8,
offset: 24,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 3,
column: 9,
offset: 25,
},
},
},
Token {
kind: Punctuation,
spelling: "}",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 1,
offset: 26,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 2,
offset: 27,
},
},
},
Token {
kind: Identifier,
spelling: "foo",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 3,
offset: 28,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 6,
offset: 31,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 6,
offset: 31,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 4,
column: 7,
offset: 32,
},
},
},
Token {
kind: Keyword,
spelling: "int",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 1,
offset: 34,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 4,
offset: 37,
},
},
},
Token {
kind: Identifier,
spelling: "main",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 5,
offset: 38,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 9,
offset: 42,
},
},
},
Token {
kind: Punctuation,
spelling: "(",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 9,
offset: 42,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 10,
offset: 43,
},
},
},
Token {
kind: Punctuation,
spelling: ")",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 10,
offset: 43,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 6,
column: 11,
offset: 44,
},
},
},
Token {
kind: Punctuation,
spelling: "{",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 7,
column: 1,
offset: 45,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 7,
column: 2,
offset: 46,
},
},
},
Token {
kind: Identifier,
spelling: "foo",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 3,
offset: 49,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 6,
offset: 52,
},
},
},
Token {
kind: Identifier,
spelling: "f",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 7,
offset: 53,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 8,
offset: 54,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 8,
offset: 54,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 8,
column: 9,
offset: 55,
},
},
},
Token {
kind: Identifier,
spelling: "f",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 3,
offset: 58,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 4,
offset: 59,
},
},
},
Token {
kind: Punctuation,
spelling: ".",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 4,
offset: 59,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 5,
offset: 60,
},
},
},
Token {
kind: Identifier,
spelling: "a",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 5,
offset: 60,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 6,
offset: 61,
},
},
},
Token {
kind: Punctuation,
spelling: "=",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 7,
offset: 62,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 8,
offset: 63,
},
},
},
Token {
kind: Literal,
spelling: "0",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 9,
offset: 64,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 10,
offset: 65,
},
},
},
Token {
kind: Punctuation,
spelling: ";",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 10,
offset: 65,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 9,
column: 11,
offset: 66,
},
},
},
Token {
kind: Punctuation,
spelling: "}",
range: SourceRange {
start: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 10,
column: 1,
offset: 67,
},
end: SourceLocation {
file: Some(
File {
path: "test/simple.c",
},
),
line: 10,
column: 2,
offset: 68,
},
},
},
]
annotated: [
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
]
children: Map {
iter: Iter(
[
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
),
}
Thanks for the help!
Creating an instance of Clang
involves calling clang-sys::load()
which dynamically loads the clang library for the currently executing thread.
With Clang: Send
(which is implemented automatically due to the auto-trait rules) the abstraction leaks when you do something like:
let clang = Clang::new();
std::thread::spawn(|| {
/* use clang here */
});
When code is written this way, clang
attempts to directly access functions from libclang
without checking whether the library is loaded and fail at the assert here.
This bug occurred in actual code here https://github.com/twistedfall/opencv-rust/blob/master/build.rs#L99-L116
Ultimately I think using thread-local storage here is really an instance of superfluous complexity and the library would be way better off with plain global shared variable with an atomic and a std::sync::Once
or a lazy_static
.
Hey,
Is there a way to obtain the inside type of a const type.
I know in the api I can invoke.
type_.is_const_qualified()
but how can I obtain the type that is const qualified?
For example if I have a type that is:
const int
is there a way to get hold of:
int
the input c++ class is :
// file: example/structs.hpp
#include <tuple>
class foo
{
public:
foo(int n_, char c_, double d_)
: n{n_}, c{c_}, d{d_}
{}
friend bool operator<(const foo& lh, const foo& rh)
{
return std::tie(lh.n, lh.c, lh.d) <
std::tie(rh.n, rh.c, rh.d);
}
private:
int n;
char c;
double d;
};
the visit program is:
use clang::*;
fn main() {
// Acquire an instance of `Clang`
let clang = Clang::new().unwrap();
// Create a new `Index`
let index = Index::new(&clang, false, false);
// Parse a source file into a translation unit
let tu = index.parser("examples/structs.hpp").parse().unwrap();
// Get the class in this translation unit
let classes = tu
.get_entity()
.get_children()
.into_iter()
.filter(|e| e.get_kind() == EntityKind::ClassDecl)
.collect::<Vec<_>>();
for cls in classes {
visit_entity(cls, 0);
}
}
fn visit_entity(e: Entity, lev: usize) {
if let Some(t) = e.get_type() {
println!(
"{spaces}{k:?} {n:?} ",
spaces = (0..lev).map(|_| "-").collect::<String>(),
k = e.get_kind(),
n = e.get_name().unwrap_or_default()
);
for f in e.get_children() {
visit_entity(f, lev + 1)
}
}
}
the really output is:
ClassDecl "foo"
-Constructor "foo"
--ParmDecl "n_"
--ParmDecl "c_"
--ParmDecl "d_"
--MemberRef "n"
--InitListExpr ""
---UnexposedExpr "n_"
----DeclRefExpr "n_"
--MemberRef "c"
--InitListExpr ""
---UnexposedExpr "c_"
----DeclRefExpr "c_"
--MemberRef "d"
--InitListExpr ""
---UnexposedExpr "d_"
----DeclRefExpr "d_"
-FieldDecl "n"
-FieldDecl "c"
-FieldDecl "d"
Did you consider making Entity an enum? It would nable the use of pattern matching.
The C++ API allows doing this via the getOpcode()
method of the BinaryOperator
subclass of Expr
.
The lack of this feature is noted as one of the reasons Corrode was written in Haskell using Language.C
, rather than Rust
It seems that clang-rs does not search for libraries in the environment variable LIBRARY_PATH during execution of the build.rs script.
I am using GUIX (like NIX) and my library path is /gnu/store/qb41j953iam58gj3cwsz9jlnnfn25cwa-profile/lib
.
In that folder there is a libclang
and libLLVM
etc.
But it seems that the build.rs
script is instead linking with the libclang and libllvm that is present in /lib/x86_64-linux-gnu/
.
This leads to all sorts of linker errors, see snippet below:
= note: ld: /lib/x86_64-linux-gnu/libedit.so.2: undefined reference to `__isoc23_wcstol@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `arc4random@GLIBC_2.36'
ld: /lib/x86_64-linux-gnu/libbsd.so.0: undefined reference to `__isoc23_strtoimax@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `__isoc23_strtoull@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `__isoc23_sscanf@GLIBC_2.38'
ld: /usr/lib/llvm-17/lib/libclang-17.0.6.so: undefined reference to `__isoc23_strtoul@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `std::condition_variable::wait(std::unique_lock<std::mutex>&)@GLIBCXX_3.4.30'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `fmodf@GLIBC_2.38'
ld: /usr/lib/llvm-17/lib/libclang-17.0.6.so: undefined reference to `__isoc23_strtol@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `fmod@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `__isoc23_scanf@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libbsd.so.0: undefined reference to `__isoc23_strtoumax@GLIBC_2.38'
ld: /lib/x86_64-linux-gnu/libLLVM-17.so.1: undefined reference to `__isoc23_strtoll@GLIBC_2.38'
The LIBRARY_PATH
variable is a convention established by gcc
, and it makes sense to follow it.
See here https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html#index-LIBRARY_005fPATH
If LIBRARY_PATH
is set, the build.rs
script should search for libclang
and similar in all the paths specified there, before it looks anywhere else. This is compatible with how gcc
works.
This works
Cargo.toml:-
[package]
name = "bindgen_with_clang"
version = "0.1.0"
edition = "2018"
[build-dependencies]
#bindgen = "0.57.0" #uncommenting this panics the build.rs
clang = "1.0.3"
build.rs:-
use clang::*;
fn main() {
let clang = Clang::new().unwrap();
let index = Index::new(&clang, false, false);
let tu = index.parser("test.hpp").parse().unwrap();
}
But un-commentating bindgen
in Cargo.toml
does not work. It gives me following error:-
Compiling bindgen_with_clang v0.1.0 (/home/smit/bindgen_with_clang)
error: failed to run custom build command for `bindgen_with_clang v0.1.0 (/home/smit/bindgen_with_clang)`
Caused by:
process didn't exit successfully: `/home/smit/bindgen_with_clang/target/debug/build/bindgen_with_clang-b4cabdc5f6bc0d97/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'a `libclang` shared library is not loaded on this thread', /home/smit/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-sys-1.1.1/src/lib.rs:1680:1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When trying to call Entity.get_platform_availability()
, my program crashes with the following message:
malloc: *** error for object 0x100704370: pointer being freed was not allocated
Looking at the stack track in the debugger it happens inside clang_disposeCXPlatformAvailability
.
Having a look at the clang source code, clang_disposeCXPlatformAvailability
is pretty simple:
void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
clang_disposeString(availability->Platform);
clang_disposeString(availability->Message);
}
It seems at least one of the strings has been freed somewhere else.
And looking a bit more at the clang-rs source they are indeed already freed when converted to Rust string:
impl PlatformAvailability {
fn from_raw(mut raw: CXPlatformAvailability) -> PlatformAvailability {
let availability = PlatformAvailability {
platform: utility::to_string(raw.Platform),
unavailable: raw.Unavailable != 0,
introduced: raw.Introduced.map(Version::from_raw),
deprecated: raw.Deprecated.map(Version::from_raw),
obsoleted: raw.Obsoleted.map(Version::from_raw),
message: utility::to_string_option(raw.Message),
};
unsafe { clang_disposeCXPlatformAvailability(&mut raw); }
availability
}
}
with utility::to_string
being:
pub fn to_string(clang: CXString) -> String {
unsafe {
let c = CStr::from_ptr(clang_getCString(clang));
let rust = c.to_str().expect("invalid Rust string").into();
clang_disposeString(clang);
rust
}
}
I'm not sure it is the best fix but I guess removing the call to clang_disposeCXPlatformAvailability
would fix the crash?
README.md still refers to CONTRIBUTING.md that was removed in 0d5d4d2.
It's possible to construct Clang
with
let cl = clang::Clang;
instead of
let cl = clang::Clang::new().unwrap();
This violates the requirement that only one Clang
object exists per thread. The way to fix it is to give the struct a private inner type.
struct ClangInner; // Private, so can't construct `Clang` without `Clang::new()`
pub struct Clang(ClangInner);
clang.exe has a switch to parse .h as cpp header file with "-x c++", or use clang++.exe
I want to parse a c++ header file with .h extension, now I can only rename it to .hpp to get parse correct.
Does libclang support this? Can this add to clang-rs?
Using main branch with clang15.0.3, run cargo test locally, I got error
libclang: clang version 15.0.3 (https://github.com/llvm/llvm-project.git 4a2c05b05ed07f1f620e94f6524a8b4b2760a0b1)
thread 'test' panicked at 'assertion failed: `(left == right)`
left: `7`,
right: `6`', tests/completion.rs:58:13
stack backtrace:
0: rust_begin_unwind
at /rustc/a6b7274a462829f8ef08a1ddcdcec7ac80dbf3e1/library/std/src/panicking.rs:556:5
1: core::panicking::panic_fmt
at /rustc/a6b7274a462829f8ef08a1ddcdcec7ac80dbf3e1/library/core/src/panicking.rs:142:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed
at /rustc/a6b7274a462829f8ef08a1ddcdcec7ac80dbf3e1/library/core/src/panicking.rs:181:5
4: tests::completion_test::test::{{closure}}
at ./tests/completion.rs:58:13
5: tests::with_temporary_file::{{closure}}
at ./tests/tests.rs:69:55
6: tests::with_temporary_files::{{closure}}
at ./tests/tests.rs:80:9
7: tests::with_temporary_directory
at ./tests/tests.rs:64:5
8: tests::with_temporary_files
at ./tests/tests.rs:73:5
9: tests::with_temporary_file
at ./tests/tests.rs:69:5
10: tests::completion_test::test
at ./tests/completion.rs:17:5
11: tests::test
at ./tests/tests.rs:123:5
12: tests::test::{{closure}}
at ./tests/tests.rs:118:1
13: core::ops::function::FnOnce::call_once
at /rustc/a6b7274a462829f8ef08a1ddcdcec7ac80dbf3e1/library/core/src/ops/function.rs:251:5
14: core::ops::function::FnOnce::call_once
at /rustc/a6b7274a462829f8ef08a1ddcdcec7ac80dbf3e1/library/core/src/ops/function.rs:251:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
test test ... FAILED
It seems this clang version produces different results.get_results()
[
CompletionResult {
kind: FieldDecl,
string: CompletionString {
chunks: [
ResultType(
"int",
),
TypedText(
"a",
),
],
},
},
CompletionResult {
kind: StructDecl,
string: CompletionString {
chunks: [
TypedText(
"A",
),
Text(
"::",
),
],
},
},
CompletionResult {
kind: FieldDecl,
string: CompletionString {
chunks: [
ResultType(
"int",
),
TypedText(
"b",
),
],
},
},
CompletionResult {
kind: FieldDecl,
string: CompletionString {
chunks: [
ResultType(
"int",
),
TypedText(
"c",
),
],
},
},
CompletionResult {
kind: Destructor,
string: CompletionString {
chunks: [
ResultType(
"void",
),
TypedText(
"~A",
),
LeftParenthesis,
RightParenthesis,
],
},
},
CompletionResult {
kind: Method,
string: CompletionString {
chunks: [
ResultType(
"A &",
),
TypedText(
"operator=",
),
LeftParenthesis,
Placeholder(
"const A &",
),
RightParenthesis,
],
},
},
CompletionResult {
kind: Method,
string: CompletionString {
chunks: [
ResultType(
"A &",
),
TypedText(
"operator=",
),
LeftParenthesis,
Placeholder(
"A &&",
),
RightParenthesis,
],
},
},
]
Hello,
Thanks for this project. I am trying to use it on windows, but none the test pass because I get the following error:
thread 'test' panicked at 'a `libclang` shared library is not loaded on this thread', src\libcore\option.rs:1038:5
I updated Cargo.toml for clang-sys to use the master branch since those tests pass.
clang-sys = { git="https://github.com/KyleMayes/clang-sys.git", branch="master", features = ["runtime", "clang_6_0"] }
What is extra strange is that clang-sys on its own passes both the tests:
C:\Users\dev\Projects\clang-sys>cargo test
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
Running target\debug\deps\clang_sys-ae7cfce2797a2aee.exe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target\debug\deps\lib-fca0a27cb6a671d0.exe
running 2 tests
test test ... ok
test test_support ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests clang-sys
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Here is my clang version:
C:\Users\dev\Projects\clang-rs>clang --version
clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
I am using Microsoft Windows 10 Pro.
This is detectable through the standard library's debug assertions, which are currently only usable on a nightly compiler with -Zbuild-std
, or if you build your own compiler and standard library with them enabled. That's what was done in the crater run which yielded this build log: https://crater-reports.s3.amazonaws.com/pr-101929/try%233bbb5242a8064de4ca3af4036745ddf603ddaa85/reg/printimg-0.5.5/log.txt among many others.
The problem (if it exists) is in this code:
Lines 447 to 449 in 79f83c7
It's not uncommon for C APIs to return a null pointer and 0 length (font-kit
has made the same mistake), but in Rust it's not valid to construct a slice from a null pointer, because slice::from_raw_parts
actually returns a reference and references must not be null.
Here is the top of a backtrace from a core dump from one of many crates which depend on opencv
, whose build process depends on version 1 of this crate:
#0 core::slice::raw::from_raw_parts::runtime<clang_sys::CXToken> () at /home/ben/rust/library/core/src/slice/raw.rs:93
#1 core::slice::raw::from_raw_parts<clang_sys::CXToken> (data=0x0, len=0)
at /home/ben/rust/library/core/src/intrinsics.rs:2195
#2 0x0000557e09566b31 in clang::source::SourceRange::tokenize (self=0x7fabfb1ef0f0) at src/source.rs:449
#3 0x0000557e0932c838 in opencv_binding_generator::field::Field::default_value (self=0x7fabfb1ef320) at src/field.rs:98
#4 0x0000557e0933380a in opencv_binding_generator::func::{impl#5}::rendered_doc_comment_with_prefix::{closure#1} (
out=0x7fabfb1ef638) at src/func.rs:609
I'd be submitting a patch, but one thing here is odd: I can only find these null slices from crates which use version 1 of this crate. Perhaps version 2 is just not used very much yet (it is surely used much less than clang-rs version 1, by about a factor of 9). Or maybe this bug doesn't come up because of some subtle change elsewhere in this library. I'm just not sure, but the fact that the code linked above doesn't check for null is suspicious.
I have spent several hours, but can't find solution. Please help..
I have some macro in header file like:
#define SomeThing '1'
in Rust I have these code:
let clang = Clang::new().unwrap();
let index = Index::new(&clang, false, false);
let tu = index.parser("file_path")
.arguments(&["-x", "c++"])
.detailed_preprocessing_record(true) // for macro
.parse()
.unwrap();
let children = tu.get_entity().get_children().into_iter();
for cursor in children {
match cursor.get_kind() {
EntityKind::MacroDefinition => {
// I can get macro name here, but can't get macro value.
}
}
}
the solution for python:
tu = index.parse(sys.argv[1], options=clang.cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD)
def visit(node):
if node.kind in (clang.cindex.CursorKind.MACRO_INSTANTIATION, clang.cindex.CursorKind.MACRO_DEFINITION):
print 'Found %s Type %s DATA %s Extent %s [line=%s, col=%s]' % (node.displayname, node.kind, node.data, node.extent, node.location.line, node.location.column)
for c in node.get_children():
visit(c)
but I can't find some method like "node.data" in clang-rs.
I'm unsure how this works, but looking at EntityKind
, I don't see a variant representing __attribute__((noreturn))
. Is that possible to add or is it not or how is it?
https://kylemayes.github.io/clang-rs/8_0/clang
This link 404s.
I know that it's possible to compile C source data to obj-file, or executable files with libclang
.
Could you provide some practical example in rust for libclang
for very basic operations that possible to do with CLI:
clang myfile.c -c -o myfile.o
clang myfile2.c myfile.o -o myapp
It will be really helpful to know how to do that with Rust using libclang
.
Or to do the same things for ll
files (LLVM IR source files).
Essentially I'm trying to replicate what this repo does (which is follow all the headers recursively and process all their declarations) but it starts with calling an API upon clang::HeaderSearch
:
Wondering how to do the same thing in clang-rs
.
When trying to print SourceError
, the program goes into infinite recursion and fails with stack overflow. In my case, I tried to print the error after unsuccessful parsing of nonexistent file.
For file:
extern crate clang;
use clang::*;
fn main() {
let clang = Clang::new().unwrap();
let index = Index::new(&clang, false, false);
let _tu = index.parser("nonexistent.c").parse().unwrap();
}
…I've got the following error:
$ cargo run
Compiling libclang-error v0.1.0 (/home/nawordar/projects/tests/rust/libclang-error)
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Running `target/debug/libclang-error`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Unknown', src/main.rs:8:15
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When I changed the code to:
extern crate clang;
use clang::*;
fn main() {
let clang = Clang::new().unwrap();
let index = Index::new(&clang, false, false);
let tu = index.parser("nonexistent.c").parse();
if let Err(err) = tu {
println!("{}", err);
}
}
…I had a segfault:
$ cargo run
Compiling libclang-error v0.1.0 (/home/nawordar/projects/tests/rust/libclang-error)
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Running `target/debug/libclang-error`
zsh: segmentation fault (core dumped) cargo run
I have debugged it with gdb and it repeatedly executes line src/error.rs:66
until SIGSEGV:
$ gdb target/debug/libclang-error
GNU gdb (GDB) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from target/debug/libclang-error...
warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts
of file /home/nawordar/projects/tests/rust/libclang-error/target/debug/libclang-error.
Use `info auto-load python-scripts [REGEXP]' to list them.
(gdb) r
Starting program: /home/nawordar/projects/tests/rust/libclang-error/target/debug/libclang-error
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7fffee01e640 (LWP 86175)]
[Thread 0x7fffee01e640 (LWP 86175) exited]
Thread 1 "libclang-error" received signal SIGSEGV, Segmentation fault.
core::fmt::write () at src/libcore/fmt/mod.rs:1060
1060 src/libcore/fmt/mod.rs: No such file or directory.
(gdb) backtrace
#0 core::fmt::write () at src/libcore/fmt/mod.rs:1060
#1 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#2 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ff150)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#3 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ff248, f=0x7fffff7ff150)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#4 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
#5 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#6 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ff2e0)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#7 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ff3d8, f=0x7fffff7ff2e0)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#8 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
#9 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#10 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ff470)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#11 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ff568, f=0x7fffff7ff470)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#12 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
#13 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#14 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ff600)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#15 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ff6f8, f=0x7fffff7ff600)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#16 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
#17 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#18 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ff790)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#19 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ff888, f=0x7fffff7ff790)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#20 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
#21 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#22 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ff920)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#23 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ffa18, f=0x7fffff7ff920)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#24 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
#25 0x000055555558a774 in core::fmt::Formatter::write_fmt () at src/libcore/fmt/mod.rs:1505
#26 0x000055555555cfca in <clang::error::SourceError as core::fmt::Display>::fmt (self=0x7fffffffdbb7,
formatter=0x7fffff7ffab0)
at /home/nawordar/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-1.0.1/src/error.rs:66
#27 0x000055555555ceb7 in <&T as core::fmt::Display>::fmt (self=0x7fffff7ffba8, f=0x7fffff7ffab0)
at /home/nawordar/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1981
#28 0x0000555555589b1c in core::fmt::write () at src/libcore/fmt/mod.rs:1076
Currently maps to:
pub fn is_function_like_macro(&self) -> bool {
unsafe { clang_Cursor_isFunctionInlined(self.raw) != 0 }
}
Should be:
pub fn is_function_like_macro(&self) -> bool {
unsafe { clang_Cursor_isMacroFunctionLike(self.raw) != 0 }
}
I will create a pull request for this change in a second.
Hi Kyle,
Can you please explain reasoning behind disabling autoimpls for Send and Sync in the new release of clang
? Is it just a precaution or is there some issue with that?
Thanks!
Hey,
any particular reason you haven't bumped the clang-sys dependency? 0.8 enables me to build under OS X.
Hi,
Is there any possibility to access the location information for a type?
I'm doing roughly the following:
fn_entity
.get_type().unwrap()
.get_argument_types().unwrap()
.into_iter()
.for_each(|t:Type| {
// get location information for 'type' here
})
Thanks a lot,
Sebastian.
Recent bindgen
s depend on clang-sys ^0.26. The most recent release of clang-rs depends on 0.23
. That unfortunately means I can't use both in the same project (see bluejekyll/pg-extend-rs#20 for my motivating example)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.