├── .gitattributes ├── tests ├── functional │ ├── syntax_error.d │ ├── comments_disabled.d │ ├── variables.h │ ├── typedef.h │ ├── globalImports.h │ ├── comments_disabled.h │ ├── comments_enabled.d │ ├── comments_enabled.h │ ├── syntax_error.h │ ├── test_package │ │ ├── .gitignore │ │ ├── source │ │ │ └── main.d │ │ └── dub.sdl │ ├── graph │ │ ├── subfile1.h │ │ ├── subfile3.h │ │ ├── subsubfile3.h │ │ ├── self_including_main.h │ │ ├── subsubfile1.h │ │ ├── subsubfile2.h │ │ ├── file.h │ │ ├── subfile2.h │ │ └── self_including.h │ ├── include │ │ ├── subfile1.h │ │ ├── subfile3.h │ │ ├── subsubfile1.h │ │ ├── subfile2.h │ │ └── file.h │ ├── multiThreadTest1.h │ ├── multiThreadTest2.h │ ├── objc │ │ ├── classes.h │ │ ├── protocols.h │ │ ├── classes.d │ │ ├── protocols.d │ │ ├── categories.h │ │ ├── time_h_issue.h │ │ ├── cgfloat.d │ │ ├── cgfloat.h │ │ ├── time_h_issue.d │ │ ├── categories.d │ │ ├── primitives.h │ │ ├── properties.h │ │ ├── primitives.d │ │ ├── properties.d │ │ ├── methods.h │ │ └── methods.d │ ├── typedef.d │ ├── variables.d │ ├── include.h │ ├── multiThreadTest1.d │ ├── multiThreadTest2.d │ ├── module │ │ ├── include.h │ │ ├── unused.h │ │ ├── main0.h │ │ ├── main0_public.h │ │ ├── main0NotNormalized.h │ │ ├── main0.d │ │ ├── main0_public.d │ │ ├── include.d │ │ ├── main0NotNormalized.d │ │ └── unused.d │ ├── typedef_struct.h │ ├── dynamic_struct.d │ ├── dynamic_struct.h │ ├── arrays.h │ ├── globalImports.d │ ├── include.d │ ├── typedef_struct.d │ ├── collision.h │ ├── function_pointers.h │ ├── functions.h │ ├── preprocessor.h │ ├── arrays.d │ ├── functions.d │ ├── preprocessor.d │ ├── const.d │ ├── aggregate.h │ ├── function_pointers.d │ ├── aggregate.d │ ├── const.h │ ├── unions.h │ ├── primitives.h │ ├── enums.h │ ├── comments.h │ ├── unions.d │ ├── comments.d │ ├── structs.h │ ├── enums.d │ ├── primitives.d │ ├── structs.d │ └── clang-c │ │ ├── Platform.d │ │ ├── Platform.h │ │ ├── CXErrorCode.d │ │ ├── CXString.d │ │ ├── CXErrorCode.h │ │ ├── CXString.h │ │ ├── LICENSE.TXT │ │ ├── BuildSystem.d │ │ └── CXCompilationDatabase.d ├── unit │ ├── main.d │ ├── issues │ │ ├── Issue107.d │ │ ├── Issue199.d │ │ ├── issue286_leading_dot.d │ │ ├── Issue214.d │ │ ├── Issue123.d │ │ ├── Issue106.d │ │ ├── Issue138.d │ │ ├── Issue114.d │ │ ├── Issue98.d │ │ ├── Issue85.d │ │ ├── Issue20.d │ │ ├── issue288_int128.d │ │ ├── Issue216.d │ │ ├── Issue38.d │ │ ├── Issue192.d │ │ ├── Issue116.d │ │ ├── Issue102.d │ │ ├── Issue140.d │ │ ├── Issue10.d │ │ ├── Issue203.d │ │ ├── Issue204.d │ │ ├── Issue202.d │ │ ├── Issue160.d │ │ ├── Issue166.d │ │ ├── Issue8.d │ │ ├── Issue46.d │ │ ├── Issue141.d │ │ ├── Issue137.d │ │ └── Issue58.d │ ├── CommentIndexTests.d │ ├── IncludeHandlerTests.d │ ├── TranslateEnumValuesUnitTests.d │ ├── IncludeGraphTests.d │ ├── TypeInferenceTests.d │ ├── FormattingUnitTest.d │ ├── BitFieldsTests.d │ └── Assert.d └── support │ └── Assertions.d ├── dub.selections.json ├── run.sh ├── .editorconfig ├── resources ├── readme.md ├── __stddef_max_align_t.h ├── stdbool.h ├── stdarg.h ├── limits.h └── stddef.h ├── .gitmodules ├── .gitignore ├── dstep ├── core │ └── Exceptions.d ├── main.d ├── driver │ ├── Util.d │ └── Application.d └── translator │ ├── Util.d │ ├── objc │ └── Category.d │ ├── Declaration.d │ ├── TypedefIndex.d │ ├── Options.d │ ├── MacroIndex.d │ └── ConvertCase.d ├── clang ├── Index.d ├── File.d ├── c │ ├── Platform.d │ ├── FatalErrorHandler.d │ ├── Rewrite.d │ ├── CXErrorCode.d │ ├── CXString.d │ ├── CXCompilationDatabase.d │ └── BuildSystem.d ├── Token.d ├── SourceRange.d ├── SourceLocation.d ├── Compiler.d └── Diagnostic.d ├── generate_libclang_bindings.sh ├── tools ├── build_release.ps1 ├── generate_version.d ├── build_release.sh └── install_dc.ps1 ├── todo.taskpaper ├── library_test.d ├── CONTRIBUTING.md ├── ci.sh ├── dub.json ├── test.d └── .github └── workflows └── support └── build └── action.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | * -text 2 | -------------------------------------------------------------------------------- /tests/functional/syntax_error.d: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/functional/comments_disabled.d: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/functional/variables.h: -------------------------------------------------------------------------------- 1 | int a; -------------------------------------------------------------------------------- /tests/functional/typedef.h: -------------------------------------------------------------------------------- 1 | typedef int foo; -------------------------------------------------------------------------------- /tests/functional/globalImports.h: -------------------------------------------------------------------------------- 1 | int foo; 2 | -------------------------------------------------------------------------------- /tests/functional/comments_disabled.h: -------------------------------------------------------------------------------- 1 | /* Test, test */ -------------------------------------------------------------------------------- /tests/functional/comments_enabled.d: -------------------------------------------------------------------------------- 1 | /* Test, test */ -------------------------------------------------------------------------------- /tests/functional/comments_enabled.h: -------------------------------------------------------------------------------- 1 | /* Test, test */ -------------------------------------------------------------------------------- /tests/functional/syntax_error.h: -------------------------------------------------------------------------------- 1 | syntax_error.h 2 | -------------------------------------------------------------------------------- /tests/functional/test_package/.gitignore: -------------------------------------------------------------------------------- 1 | test_package -------------------------------------------------------------------------------- /tests/functional/graph/subfile1.h: -------------------------------------------------------------------------------- 1 | 2 | int content; 3 | -------------------------------------------------------------------------------- /tests/functional/graph/subfile3.h: -------------------------------------------------------------------------------- 1 | 2 | void core(int); 3 | -------------------------------------------------------------------------------- /tests/functional/include/subfile1.h: -------------------------------------------------------------------------------- 1 | 2 | int content; 3 | -------------------------------------------------------------------------------- /tests/functional/multiThreadTest1.h: -------------------------------------------------------------------------------- 1 | void func1(void); 2 | -------------------------------------------------------------------------------- /tests/functional/multiThreadTest2.h: -------------------------------------------------------------------------------- 1 | void func2(void); 2 | -------------------------------------------------------------------------------- /tests/functional/objc/classes.h: -------------------------------------------------------------------------------- 1 | @interface Foo 2 | @end -------------------------------------------------------------------------------- /tests/functional/objc/protocols.h: -------------------------------------------------------------------------------- 1 | @protocol Foo 2 | @end -------------------------------------------------------------------------------- /tests/functional/graph/subsubfile3.h: -------------------------------------------------------------------------------- 1 | 2 | int subsubfile3; 3 | -------------------------------------------------------------------------------- /tests/functional/include/subfile3.h: -------------------------------------------------------------------------------- 1 | 2 | void core(int); 3 | -------------------------------------------------------------------------------- /tests/functional/include/subsubfile1.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | int baz; 4 | -------------------------------------------------------------------------------- /tests/functional/typedef.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | alias foo = int; -------------------------------------------------------------------------------- /tests/functional/variables.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | extern __gshared int a; -------------------------------------------------------------------------------- /tests/functional/include.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t a; 4 | FILE b; -------------------------------------------------------------------------------- /tests/functional/multiThreadTest1.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | void func1 (); 4 | -------------------------------------------------------------------------------- /tests/functional/multiThreadTest2.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | void func2 (); 4 | -------------------------------------------------------------------------------- /dub.selections.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileVersion": 1, 3 | "versions": { 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/functional/graph/self_including_main.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /tests/functional/graph/subsubfile1.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int baz; 5 | -------------------------------------------------------------------------------- /tests/functional/objc/classes.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | class Foo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /tests/functional/module/include.h: -------------------------------------------------------------------------------- 1 | 2 | typedef struct Foo { 3 | int qux; 4 | } Bar; 5 | -------------------------------------------------------------------------------- /tests/functional/objc/protocols.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | interface Foo 4 | { 5 | } -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | ./build.sh 6 | ./bin/dstep foo.h -o /dev/stdout 7 | -------------------------------------------------------------------------------- /tests/functional/graph/subsubfile2.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int subsubfile2; 5 | -------------------------------------------------------------------------------- /tests/functional/module/unused.h: -------------------------------------------------------------------------------- 1 | 2 | typedef struct Unused_T { 3 | int qux; 4 | } Unused; 5 | -------------------------------------------------------------------------------- /tests/functional/objc/categories.h: -------------------------------------------------------------------------------- 1 | @interface Foo 2 | @end 3 | 4 | @interface Foo (Ext) 5 | @end -------------------------------------------------------------------------------- /tests/functional/objc/time_h_issue.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | time_t getFileTime(unsigned file); 4 | -------------------------------------------------------------------------------- /tests/functional/include/subfile2.h: -------------------------------------------------------------------------------- 1 | 2 | int foo; 3 | 4 | #include "subsubfile1.h" 5 | 6 | int bar; 7 | -------------------------------------------------------------------------------- /tests/functional/module/main0.h: -------------------------------------------------------------------------------- 1 | #include "include.h" 2 | #include "unused.h" 3 | 4 | void foo(Bar bar); 5 | -------------------------------------------------------------------------------- /tests/functional/typedef_struct.h: -------------------------------------------------------------------------------- 1 | typedef struct _Foo Foo; 2 | 3 | struct _Foo 4 | { 5 | int x; 6 | }; 7 | -------------------------------------------------------------------------------- /tests/functional/dynamic_struct.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | struct Dynamic 4 | { 5 | int x; 6 | int[0] data; 7 | } -------------------------------------------------------------------------------- /tests/functional/dynamic_struct.h: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | struct Dynamic 4 | { 5 | int x; 6 | int[0] data; 7 | } -------------------------------------------------------------------------------- /tests/functional/module/main0_public.h: -------------------------------------------------------------------------------- 1 | #include "include.h" 2 | #include "unused.h" 3 | 4 | void foo(Bar bar); 5 | -------------------------------------------------------------------------------- /tests/functional/module/main0NotNormalized.h: -------------------------------------------------------------------------------- 1 | #include "include.h" 2 | #include "unused.h" 3 | 4 | void foo(Bar bar); 5 | -------------------------------------------------------------------------------- /tests/functional/arrays.h: -------------------------------------------------------------------------------- 1 | int a[4]; 2 | int b[2][3]; 3 | int c[2][3][4]; 4 | 5 | extern const char *const sys_errlist[]; 6 | -------------------------------------------------------------------------------- /tests/functional/objc/cgfloat.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | extern __gshared CGFloat test; 4 | void bar (CGFloat foo); 5 | -------------------------------------------------------------------------------- /tests/functional/objc/cgfloat.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | CGFloat test; 4 | void bar(CGFloat foo); 5 | 6 | -------------------------------------------------------------------------------- /tests/functional/globalImports.d: -------------------------------------------------------------------------------- 1 | import fstImport; 2 | import sndImport; 3 | 4 | extern (C): 5 | 6 | extern __gshared int foo; 7 | -------------------------------------------------------------------------------- /tests/functional/graph/file.h: -------------------------------------------------------------------------------- 1 | #include "subfile1.h" 2 | #include "subfile2.h" 3 | #include "subfile3.h" 4 | #include "subsubfile2.h" 5 | -------------------------------------------------------------------------------- /tests/functional/graph/subfile2.h: -------------------------------------------------------------------------------- 1 | 2 | int foo; 3 | 4 | #include "subsubfile1.h" 5 | 6 | #include "subsubfile3.h" 7 | 8 | int bar; 9 | -------------------------------------------------------------------------------- /tests/functional/include.d: -------------------------------------------------------------------------------- 1 | import core.stdc.stdio; 2 | 3 | extern (C): 4 | 5 | extern __gshared size_t a; 6 | extern __gshared FILE b; -------------------------------------------------------------------------------- /tests/functional/objc/time_h_issue.d: -------------------------------------------------------------------------------- 1 | import core.stdc.time; 2 | 3 | extern (Objective-C): 4 | 5 | time_t getFileTime (uint file); 6 | -------------------------------------------------------------------------------- /tests/functional/module/main0.d: -------------------------------------------------------------------------------- 1 | module modules.main0; 2 | 3 | import modules.include; 4 | 5 | extern (C): 6 | 7 | void foo (Bar bar); 8 | -------------------------------------------------------------------------------- /tests/functional/objc/categories.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | class Foo 4 | { 5 | } 6 | 7 | __classext Ext : Foo 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /tests/functional/typedef_struct.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | alias Foo = _Foo; 4 | 5 | struct _Foo 6 | { 7 | int x; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /tests/functional/collision.h: -------------------------------------------------------------------------------- 1 | 2 | struct struct_and_func_share_name 3 | { 4 | int important_field; 5 | }; 6 | 7 | void struct_and_func_share_name(); 8 | -------------------------------------------------------------------------------- /tests/functional/module/main0_public.d: -------------------------------------------------------------------------------- 1 | module modules.main0_public; 2 | 3 | public import modules.include; 4 | 5 | extern (C): 6 | 7 | void foo (Bar bar); 8 | -------------------------------------------------------------------------------- /tests/functional/graph/self_including.h: -------------------------------------------------------------------------------- 1 | #ifndef SELF_INCLUDING 2 | #define SELF_INCLUDING 3 | 4 | #include 5 | 6 | #endif SELF_INCLUDING 7 | -------------------------------------------------------------------------------- /tests/functional/module/include.d: -------------------------------------------------------------------------------- 1 | module modules.include; 2 | 3 | extern (C): 4 | 5 | struct Foo 6 | { 7 | int qux; 8 | } 9 | 10 | alias Bar = Foo; 11 | -------------------------------------------------------------------------------- /tests/functional/module/main0NotNormalized.d: -------------------------------------------------------------------------------- 1 | module modules.main0NotNormalized; 2 | 3 | public import modules.include; 4 | 5 | extern (C): 6 | 7 | void foo (Bar bar); 8 | -------------------------------------------------------------------------------- /tests/functional/objc/primitives.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | id x9; 4 | Class x10; 5 | SEL x11; 6 | BOOL x12; 7 | NSUInteger x13; 8 | NSInteger x14; 9 | -------------------------------------------------------------------------------- /tests/functional/function_pointers.h: -------------------------------------------------------------------------------- 1 | void (*a) (void); 2 | int (*b) (void); 3 | void (*c) (int); 4 | int (*d) (int, int); 5 | int (*e) (int a, int b); 6 | int (*f) (int a, int b, ...); -------------------------------------------------------------------------------- /tests/functional/module/unused.d: -------------------------------------------------------------------------------- 1 | module modules.unused; 2 | 3 | extern (C): 4 | 5 | struct Unused_T 6 | { 7 | int qux; 8 | } 9 | 10 | alias Unused = Unused_T; 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /tests/functional/functions.h: -------------------------------------------------------------------------------- 1 | int foo (int a); 2 | void bar (int a, int b); 3 | void fooBar (void); 4 | int a (char*, ...); 5 | int b (int out); 6 | void freeAll(void (freeFunc)(void*)); 7 | -------------------------------------------------------------------------------- /resources/readme.md: -------------------------------------------------------------------------------- 1 | * __stddef_max_align_t.h 15.0.7 2 | * float.h - 15.0.7 3 | * float.h - 15.0.7 4 | * limits.h - 15.0.7 5 | * stdarg.h - 15.0.7 6 | * stdbool.h - 15.0.7 7 | * stddef.h - 15.0.7 8 | -------------------------------------------------------------------------------- /tests/functional/objc/properties.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface Foo 5 | 6 | @property int foo; 7 | @property int version; 8 | 9 | @end -------------------------------------------------------------------------------- /tests/functional/preprocessor.h: -------------------------------------------------------------------------------- 1 | 2 | #define FOO 0 3 | #define FOOBAR 1 4 | #define FOOBARBAZ 2 5 | 6 | #define FOOSTR "foo" 7 | #define FOOBARSTR "foobar" 8 | #define FOOBARBAZSTR "foobarbaz" 9 | -------------------------------------------------------------------------------- /tests/functional/arrays.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | extern __gshared int[4] a; 4 | extern __gshared int[3][2] b; 5 | extern __gshared int[4][3][2] c; 6 | 7 | extern __gshared const(char*)[] sys_errlist; 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mambo"] 2 | path = mambo 3 | url = git://github.com/jacob-carlborg/mambo.git 4 | [submodule "dstack"] 5 | path = dstack 6 | url = git://github.com/jacob-carlborg/dstack.git 7 | -------------------------------------------------------------------------------- /tests/functional/functions.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | int foo (int a); 4 | void bar (int a, int b); 5 | void fooBar (); 6 | int a (char*, ...); 7 | int b (int out_); 8 | void freeAll (void function (void*) freeFunc); -------------------------------------------------------------------------------- /tests/functional/test_package/source/main.d: -------------------------------------------------------------------------------- 1 | import std.stdio : writeln; 2 | import clang.Util : clangVersionString; 3 | 4 | void main(string[] args) 5 | { 6 | writeln("with ", clangVersionString); 7 | } 8 | -------------------------------------------------------------------------------- /tests/functional/preprocessor.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | enum FOO = 0; 4 | enum FOOBAR = 1; 5 | enum FOOBARBAZ = 2; 6 | 7 | enum FOOSTR = "foo"; 8 | enum FOOBARSTR = "foobar"; 9 | enum FOOBARBAZSTR = "foobarbaz"; 10 | -------------------------------------------------------------------------------- /tests/functional/include/file.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include "subfile1.h" 5 | 6 | 7 | 8 | 9 | #include "subfile2.h" 10 | 11 | 12 | 13 | 14 | #include "subfile3.h" 15 | 16 | 17 | #include "subfile2.h" 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/functional/objc/primitives.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | extern __gshared ObjcObject x9; 4 | extern __gshared Class x10; 5 | extern __gshared SEL x11; 6 | extern __gshared bool x12; 7 | extern __gshared NSUInteger x13; 8 | extern __gshared NSInteger x14; 9 | -------------------------------------------------------------------------------- /tests/functional/const.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | extern __gshared const int a; 4 | extern __gshared const(int)* b; 5 | extern __gshared int* c; 6 | extern __gshared const int* d; 7 | extern __gshared const(int*)* e; 8 | extern __gshared const int** f; 9 | extern __gshared int** g; -------------------------------------------------------------------------------- /tests/functional/objc/properties.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | class Foo 4 | { 5 | @property int foo () @selector("foo"); 6 | @property void foo (int) @selector("setFoo:"); 7 | @property int version_ () @selector("version"); 8 | @property void version_ (int) @selector("setVersion:"); 9 | } -------------------------------------------------------------------------------- /tests/functional/aggregate.h: -------------------------------------------------------------------------------- 1 | int b (int out); 2 | 3 | struct Foo 4 | { 5 | int a; 6 | }; 7 | 8 | float foo(struct Foo x); 9 | float bar(struct Foo x); 10 | 11 | int a; 12 | 13 | struct Bar 14 | { 15 | int x; 16 | int y; 17 | }; 18 | 19 | const char* q; 20 | 21 | int (*e) (int a, int b); 22 | -------------------------------------------------------------------------------- /tests/functional/function_pointers.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | extern __gshared void function () a; 4 | extern __gshared int function () b; 5 | extern __gshared void function (int) c; 6 | extern __gshared int function (int, int) d; 7 | extern __gshared int function (int a, int b) e; 8 | extern __gshared int function (int a, int b, ...) f; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.h 2 | !tests/functional/**/*.h 3 | !tests/functional/*.h 4 | !resources/*.h 5 | *.deps 6 | *.a 7 | *.o 8 | *.dylib 9 | *.lib 10 | *.dll 11 | *.exe 12 | *.so 13 | main 14 | tmp 15 | .rvmrc 16 | foo.d 17 | *.zip 18 | *.swp 19 | .dub 20 | clangs 21 | *.gch 22 | bin/* 23 | .DS_Store 24 | resources/VERSION 25 | linker_flags.txt 26 | *.xz 27 | -------------------------------------------------------------------------------- /tests/functional/aggregate.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | int b (int out_); 4 | 5 | struct Foo 6 | { 7 | int a; 8 | } 9 | 10 | float foo (Foo x); 11 | float bar (Foo x); 12 | 13 | extern __gshared int a; 14 | 15 | struct Bar 16 | { 17 | int x; 18 | int y; 19 | } 20 | 21 | extern __gshared const(char)* q; 22 | 23 | extern __gshared int function (int a, int b) e; 24 | -------------------------------------------------------------------------------- /tests/functional/const.h: -------------------------------------------------------------------------------- 1 | const int a; // const int 2 | const int* b; // mutable pointer to const int 3 | int* const c; // const pointer to mutable int 4 | const int* const d; // const pointer to const int 5 | const int* const * e; // mutable pointer to const pointer to const int 6 | const int* const * const f; // const pointer to const pointer to const int 7 | int* const * const g; // const pointer to const pointer to mutable int -------------------------------------------------------------------------------- /tests/functional/unions.h: -------------------------------------------------------------------------------- 1 | union Foo 2 | { 3 | int a; 4 | }; 5 | 6 | union Bar 7 | { 8 | int x; 9 | } b; 10 | 11 | union Foo c; 12 | 13 | union A 14 | { 15 | union B 16 | { 17 | int x; 18 | } b; 19 | }; 20 | 21 | union C 22 | { 23 | union 24 | { 25 | int x; 26 | int y; 27 | } point; 28 | }; 29 | 30 | typedef union 31 | { 32 | int x; 33 | int y; 34 | } D; -------------------------------------------------------------------------------- /tests/functional/primitives.h: -------------------------------------------------------------------------------- 1 | long x3; 2 | long long x4; 3 | char x5; 4 | short x6; 5 | float x7; 6 | double x8; 7 | int x12; 8 | 9 | unsigned int x13; 10 | unsigned long x14; 11 | unsigned long long x15; 12 | unsigned short x16; 13 | unsigned char x17; 14 | 15 | // issue 27 16 | signed char x27; 17 | 18 | long double x18; 19 | 20 | // issue 106 21 | float _Complex x19; 22 | double _Complex x20; 23 | long double _Complex x21; 24 | -------------------------------------------------------------------------------- /tests/functional/enums.h: -------------------------------------------------------------------------------- 1 | enum Foo 2 | { 3 | a = 1 4 | }; 5 | 6 | enum Bar 7 | { 8 | b, 9 | c = 2, 10 | d = 3 11 | } e; 12 | 13 | enum Foo f; 14 | 15 | struct A 16 | { 17 | enum B 18 | { 19 | g = 1 20 | } h; 21 | }; 22 | 23 | struct C 24 | { 25 | enum 26 | { 27 | i = 1, 28 | j = 2 29 | } point; 30 | }; 31 | 32 | typedef enum 33 | { 34 | k = 1, 35 | l = 2 36 | } D; 37 | -------------------------------------------------------------------------------- /tests/unit/main.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: May 16, 2018 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module tests.unit.main; 8 | 9 | shared static this() 10 | { 11 | import std.stdio : writeln; 12 | import clang.Util : clangVersionString; 13 | 14 | writeln("with ", clangVersionString); 15 | } 16 | -------------------------------------------------------------------------------- /dstep/core/Exceptions.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Oct 1, 2011 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.core.Exceptions; 8 | 9 | class DStepException : Exception 10 | { 11 | this (string message, string file = __FILE__, size_t line = __LINE__) 12 | { 13 | super(message, file, line); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/functional/comments.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Header comment should keep to be header comment. 3 | */ 4 | 5 | /* Comment before a variable. */ 6 | int variable; 7 | 8 | /* Loose comment */ /* Loose comment */ 9 | 10 | /* 11 | Multi-line loose comment. 12 | Multi-line loose comment. 13 | Multi-line loose comment. 14 | Multi-line loose comment. 15 | Multi-line loose comment. 16 | */ /* Loose comment */ 17 | 18 | /* Comment before a function declaration. */ 19 | int func(int a, int b); 20 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue107.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jan 15, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 107: Handle typedef of opaque structs. 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | typedef struct foo foo; 15 | C", 16 | q"D 17 | extern (C): 18 | 19 | struct foo; 20 | D"); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /tests/functional/test_package/dub.sdl: -------------------------------------------------------------------------------- 1 | name "test_package" 2 | description "Tests that dstep can be used as a library" 3 | authors "Atila Neves" 4 | copyright "Copyright © 2017, Atila Neves" 5 | license "boost" 6 | targetType "executable" 7 | dependency "dstep" path="../../.." 8 | subConfiguration "dstep" "library" 9 | importPaths "../../.." 10 | // actual projects would probably just have 11 | // `libs "clang"` but since this will run under dstep's CI 12 | // we copy the linker flags here 13 | libs "version" platform="windows" 14 | -------------------------------------------------------------------------------- /tests/functional/unions.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | union Foo 4 | { 5 | int a; 6 | } 7 | 8 | union Bar 9 | { 10 | int x; 11 | } 12 | 13 | extern __gshared Bar b; 14 | 15 | extern __gshared Foo c; 16 | 17 | union A 18 | { 19 | union B 20 | { 21 | int x; 22 | } 23 | 24 | B b; 25 | } 26 | 27 | union C 28 | { 29 | union _Anonymous_0 30 | { 31 | int x; 32 | int y; 33 | } 34 | 35 | _Anonymous_0 point; 36 | } 37 | 38 | union D 39 | { 40 | int x; 41 | int y; 42 | } 43 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue199.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 29, 2018 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | #include 15 | 16 | #define __le64 uint64_t 17 | C", 18 | q"D 19 | extern (C): 20 | 21 | alias __le64 = ulong; 22 | D"); 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /dstep/main.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 5 | */ 6 | module dstep.main; 7 | 8 | version (unittest) { } 9 | else: 10 | 11 | /** 12 | * Application entry point, handles CLI/config and forwards to 13 | * dstep.driver.Application to do actual work. 14 | */ 15 | int main (string[] args) 16 | { 17 | import dstep.driver.CommandLine: run; 18 | return run(args); 19 | } 20 | -------------------------------------------------------------------------------- /tests/functional/comments.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Header comment should keep to be header comment. 3 | */ 4 | 5 | extern (C): 6 | 7 | /* Comment before a variable. */ 8 | extern __gshared int variable; 9 | 10 | /* Loose comment */ /* Loose comment */ 11 | 12 | /* 13 | Multi-line loose comment. 14 | Multi-line loose comment. 15 | Multi-line loose comment. 16 | Multi-line loose comment. 17 | Multi-line loose comment. 18 | */ /* Loose comment */ 19 | 20 | /* Comment before a function declaration. */ 21 | int func (int a, int b); 22 | -------------------------------------------------------------------------------- /tests/functional/objc/methods.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface Foo 5 | 6 | + (void) classMethod; 7 | - (void) instanceMethod; 8 | 9 | + (void)initialize; 10 | + (id)new; 11 | + (Class)class; 12 | - (id)init; 13 | 14 | + (id)allocWithZone:(NSZone *)zone; 15 | - (IMP)methodForSelector:(SEL)aSelector; 16 | 17 | + (NSInteger)version; 18 | + (void)setVersion:(NSInteger)aVersion; 19 | + (NSUInteger) NSUIntegerTest; 20 | 21 | - (id)performSelector:(SEL)aSelector withObject:(id)object; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /tests/functional/structs.h: -------------------------------------------------------------------------------- 1 | struct Foo 2 | { 3 | int a; 4 | }; 5 | 6 | struct Bar 7 | { 8 | int x; 9 | } b; 10 | 11 | struct Foo c; 12 | 13 | struct A 14 | { 15 | struct B 16 | { 17 | int x; 18 | } b; 19 | }; 20 | 21 | struct C 22 | { 23 | struct 24 | { 25 | int x; 26 | int y; 27 | } point; 28 | }; 29 | 30 | typedef struct 31 | { 32 | int x; 33 | int y; 34 | } D; 35 | 36 | struct E; 37 | 38 | struct E 39 | { 40 | }; 41 | 42 | struct F; 43 | 44 | struct Nested 45 | { 46 | struct C field; 47 | }; 48 | -------------------------------------------------------------------------------- /tests/unit/issues/issue286_leading_dot.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2023 Jacob Carlborg. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: July 28, 2023 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | enum 15 | { 16 | Foo 17 | }; 18 | 19 | #define Bar Foo 20 | C", 21 | 22 | q"D 23 | extern (C): 24 | 25 | enum 26 | { 27 | Foo = 0 28 | } 29 | 30 | enum Bar = Foo; 31 | D"); 32 | } 33 | -------------------------------------------------------------------------------- /dstep/driver/Util.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Nov 30, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.driver.Util; 8 | 9 | string makeDefaultOutputFile(string inputFile, bool useBaseName = true) 10 | { 11 | import std.path : baseName, setExtension; 12 | 13 | if (useBaseName) 14 | return setExtension(baseName(inputFile), "d"); 15 | 16 | return setExtension(inputFile, "d"); 17 | } 18 | -------------------------------------------------------------------------------- /clang/Index.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Oct 1, 2011 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.Index; 8 | 9 | import clang.c.Index; 10 | import clang.Util; 11 | 12 | struct Index 13 | { 14 | mixin CX; 15 | 16 | this (bool excludeDeclarationsFromPCH, bool displayDiagnostics) 17 | { 18 | cx = clang_createIndex(excludeDeclarationsFromPCH ? 1 : 0, displayDiagnostics ? 1 : 0); 19 | } 20 | } -------------------------------------------------------------------------------- /tests/unit/issues/Issue214.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: January 04, 2019 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | #define bar float 15 | #define FOO(a) (bar)(a) 16 | C", 17 | q"D 18 | extern (C): 19 | 20 | alias bar = float; 21 | 22 | extern (D) auto FOO(T)(auto ref T a) 23 | { 24 | return cast(bar) a; 25 | } 26 | D"); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /tests/functional/enums.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | enum Foo 4 | { 5 | a = 1 6 | } 7 | 8 | enum Bar 9 | { 10 | b = 0, 11 | c = 2, 12 | d = 3 13 | } 14 | 15 | extern __gshared Bar e; 16 | 17 | extern __gshared Foo f; 18 | 19 | struct A 20 | { 21 | enum B 22 | { 23 | g = 1 24 | } 25 | 26 | B h; 27 | } 28 | 29 | struct C 30 | { 31 | enum _Anonymous_0 32 | { 33 | i = 1, 34 | j = 2 35 | } 36 | 37 | _Anonymous_0 point; 38 | } 39 | 40 | alias i = C._Anonymous_0.i; 41 | alias j = C._Anonymous_0.j; 42 | 43 | enum D 44 | { 45 | k = 1, 46 | l = 2 47 | } 48 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue123.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 23, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Translator; 10 | 11 | // Test standard enum. 12 | unittest 13 | { 14 | assertTranslates( 15 | q"C 16 | #include 17 | 18 | #define TEST INT_MAX 19 | 20 | C", 21 | q"D 22 | import core.stdc.limits; 23 | 24 | extern (C): 25 | 26 | enum TEST = INT_MAX; 27 | 28 | D"); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /tests/functional/primitives.d: -------------------------------------------------------------------------------- 1 | import core.stdc.config; 2 | 3 | extern (C): 4 | 5 | extern __gshared c_long x3; 6 | extern __gshared long x4; 7 | extern __gshared char x5; 8 | extern __gshared short x6; 9 | extern __gshared float x7; 10 | extern __gshared double x8; 11 | extern __gshared int x12; 12 | 13 | extern __gshared uint x13; 14 | extern __gshared c_ulong x14; 15 | extern __gshared ulong x15; 16 | extern __gshared ushort x16; 17 | extern __gshared ubyte x17; 18 | 19 | extern __gshared byte x27; 20 | 21 | extern __gshared real x18; 22 | 23 | extern __gshared cfloat x19; 24 | extern __gshared cdouble x20; 25 | extern __gshared creal x21; 26 | -------------------------------------------------------------------------------- /tests/functional/structs.d: -------------------------------------------------------------------------------- 1 | extern (C): 2 | 3 | struct Foo 4 | { 5 | int a; 6 | } 7 | 8 | struct Bar 9 | { 10 | int x; 11 | } 12 | 13 | extern __gshared Bar b; 14 | 15 | extern __gshared Foo c; 16 | 17 | struct A 18 | { 19 | struct B 20 | { 21 | int x; 22 | } 23 | 24 | B b; 25 | } 26 | 27 | struct C 28 | { 29 | struct _Anonymous_0 30 | { 31 | int x; 32 | int y; 33 | } 34 | 35 | _Anonymous_0 point; 36 | } 37 | 38 | struct D 39 | { 40 | int x; 41 | int y; 42 | } 43 | 44 | struct E 45 | { 46 | } 47 | 48 | struct F; 49 | 50 | struct Nested 51 | { 52 | C field; 53 | } 54 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue106.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jan 15, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 106: Handle complex floating-point types. 11 | unittest 12 | { 13 | assertTranslates( 14 | q"C 15 | float _Complex foo; 16 | double _Complex bar; 17 | long double _Complex baz; 18 | C", 19 | q"D 20 | extern (C): 21 | 22 | extern __gshared cfloat foo; 23 | extern __gshared cdouble bar; 24 | extern __gshared creal baz; 25 | D"); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue138.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: June 04, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Options; 10 | 11 | // Fix 138: Repeated declarations cause problems. 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | extern const unsigned fe_bandwidth_name[8]; 16 | extern const unsigned fe_bandwidth_name[8]; 17 | C", 18 | q"D 19 | extern (C): 20 | 21 | extern __gshared const(uint)[8] fe_bandwidth_name; 22 | D"); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue114.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jan 21, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 114: Crash on recursive typedef. 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | typedef struct _Foo_List { 15 | void *data; 16 | struct _Foo_List *next; 17 | } Foo_List; 18 | C", 19 | q"D 20 | extern (C): 21 | 22 | struct _Foo_List 23 | { 24 | void* data; 25 | _Foo_List* next; 26 | } 27 | 28 | alias Foo_List = _Foo_List; 29 | D"); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue98.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Oct 23, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 98: dstep segfaults: Unhandled type kind cast(CXTypeKind)119. 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | struct timeval { }; 15 | 16 | void term_await_started(const struct timeval *timeout); 17 | C", 18 | q"D 19 | extern (C): 20 | 21 | struct timeval 22 | { 23 | } 24 | 25 | void term_await_started (const(timeval)* timeout); 26 | D"); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue85.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Aug 09, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 85: dstep not converting `const T x[]` to `const (T)* x`. 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | #include 15 | 16 | int complex_forward (const double data[], const size_t stride, const size_t n, double result[]); 17 | C", 18 | q"D 19 | extern (C): 20 | 21 | int complex_forward (const(double)* data, const size_t stride, const size_t n, double* result); 22 | D"); 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue20.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Aug 10, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 20: #define (simplest cases only?). 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | #define X (1) 15 | #define Y ((float)-X) 16 | #define f(x, b) ((a) + (b)) 17 | #define foo 1 18 | C", 19 | q"D 20 | extern (C): 21 | 22 | enum X = 1; 23 | enum Y = cast(float) -X; 24 | 25 | extern (D) auto f(T0, T1)(auto ref T0 x, auto ref T1 b) 26 | { 27 | return a + b; 28 | } 29 | 30 | enum foo = 1; 31 | D"); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /tests/unit/issues/issue288_int128.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2023 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: November 10, 2023 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Options; 10 | 11 | unittest 12 | { 13 | assertTranslates( 14 | q"C 15 | __int128 a(); 16 | unsigned __int128 b(); 17 | __int128_t c(); 18 | __uint128_t d(); 19 | typedef __uint128_t tb_uint128_t; 20 | C", 21 | 22 | q"D 23 | import core.int128; 24 | 25 | extern (C): 26 | 27 | Cent a (); 28 | Cent b (); 29 | Cent c (); 30 | Cent d (); 31 | alias tb_uint128_t = Cent; 32 | D", Options(reduceAliases: true)); 33 | } 34 | -------------------------------------------------------------------------------- /dstep/translator/Util.d: -------------------------------------------------------------------------------- 1 | module dstep.translator.Util; 2 | 3 | /** In recent versions of clang (at least 19.1.7), unnamed (anonymous) types will not 4 | * set the spelling field to an empty string, but instead to a message like 5 | * "enum (unnamed at [declaration_file.h:48]" 6 | * "struct (anonymous at [declaration_file.h:48]" 7 | * Either unnamed or anonymous is used. 8 | * This applies to structs, enums and unions. 9 | * 10 | * structs and unions additionally have the isAnonymous() helper which doesn't for enums. 11 | * 12 | * Usage: 13 | * cursor.spelling.isUnnamed() 14 | */ 15 | bool isUnnamed(string s){ 16 | import std.algorithm.searching; 17 | return s == "" || 18 | s.canFind("(unnamed at") || 19 | s.canFind("(anonymous at"); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /clang/File.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Jan 29, 2012 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.File; 8 | 9 | import clang.c.Index; 10 | import clang.Util; 11 | 12 | struct File 13 | { 14 | mixin CX; 15 | 16 | string name() 17 | { 18 | return toD(clang_getFileName(cx)); 19 | } 20 | 21 | string absolutePath() 22 | { 23 | import std.conv; 24 | import std.path; 25 | return name 26 | .asAbsolutePath() 27 | .asNormalizedPath() 28 | .to!string(); 29 | } 30 | 31 | string toString() 32 | { 33 | return name; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /generate_libclang_bindings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ $# -eq 0 ]; then 6 | echo 'Please specify the path to the libclang C header files' 7 | echo 'Example: ./generate_libclang_bindings.sh /opt/local/libexec/llvm-3.8/include' 8 | 9 | exit 1 10 | fi 11 | 12 | cwd=$(pwd) 13 | pushd "$1"/clang-c > /dev/null 14 | "$cwd"/bin/dstep ./*.h \ 15 | -I"$cwd/$1" \ 16 | -I"$1" \ 17 | -Iresources \ 18 | --public-submodules \ 19 | --package clang.c \ 20 | --space-after-function-name=false \ 21 | -o "$cwd"/clang/c \ 22 | --skip CXCursorVisitorBlock \ 23 | --skip CXCursorAndRangeVisitorBlock \ 24 | --skip clang_visitChildrenWithBlock \ 25 | --skip clang_findReferencesInFileWithBlock \ 26 | --skip clang_findIncludesInFileWithBlock \ 27 | --rename-enum-members 28 | 29 | popd > /dev/null 30 | rm "$cwd"/clang/c/ExternC.d 31 | -------------------------------------------------------------------------------- /tools/build_release.ps1: -------------------------------------------------------------------------------- 1 | Set-StrictMode -Version Latest 2 | $ErrorActionPreference = 'Stop' 3 | $PSDefaultParameterValues['*:ErrorAction'] = 'Stop' 4 | 5 | $appName="dstep" 6 | $targetDir="bin" 7 | $targetPath="$targetDir/$appName.exe" 8 | 9 | function Build 10 | { 11 | dub build -b release --verror --arch=$env:arch --compiler=$env:DC 12 | } 13 | 14 | function TestDstep 15 | { 16 | dub -c test-functional --verror --arch=$env:arch --compiler=$env:DC 17 | } 18 | 19 | function Version 20 | { 21 | Invoke-Expression "$targetPath --version" 22 | } 23 | 24 | function Arch 25 | { 26 | if ($env:PLATFORM -eq 'x86') { '32' } else { '64' } 27 | } 28 | 29 | function ReleaseName 30 | { 31 | "$appName-$(Version)-win$(Arch)" 32 | } 33 | 34 | function Archive 35 | { 36 | 7z a "$(ReleaseName).7z" "$targetPath" 37 | } 38 | 39 | Build 40 | TestDstep 41 | Archive 42 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue216.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: January 05, 2019 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | typedef unsigned short ushort; 15 | typedef unsigned char byte; 16 | 17 | typedef byte (*data_in) (int param, ushort address); 18 | typedef void (*data_out) (int param, ushort address, byte data); 19 | 20 | typedef struct 21 | { 22 | ushort PC; 23 | byte IM; 24 | } foo; 25 | C", 26 | q"D 27 | extern (C): 28 | 29 | alias data_in = ubyte function (int param, ushort address); 30 | alias data_out = void function (int param, ushort address, ubyte data); 31 | 32 | struct foo 33 | { 34 | ushort PC; 35 | ubyte IM; 36 | } 37 | D"); 38 | } 39 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue38.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jul 29, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import dstep.translator.Options; 9 | 10 | import Common; 11 | 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | void foo(); 16 | void bar(const char* fmt, ...); 17 | void baz(void); 18 | C", 19 | q"D 20 | extern (C): 21 | 22 | void foo (); 23 | void bar (const(char)* fmt, ...); 24 | void baz (); 25 | D"); 26 | 27 | Options options; 28 | options.zeroParamIsVararg = true; 29 | 30 | assertTranslates(q"C 31 | void foo(); 32 | void bar(const char* fmt, ...); 33 | void baz(void); 34 | C", 35 | q"D 36 | extern (C): 37 | 38 | void foo (...); 39 | void bar (const(char)* fmt, ...); 40 | void baz (); 41 | D", options); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue192.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: April 17, 2018 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | /* Yada, yada, yada, 15 | foo(a + b) = foo(a) * bar(b) + bar(a) * foo(b) 16 | bar(a + b) = bar(a) * bar(b) - foo(a) * foo(b) 17 | 18 | Yada, yada, 19 | yada, yada. 20 | 21 | Yada, yada, 22 | yada, yada. 23 | */ 24 | C", 25 | q"D 26 | /* Yada, yada, yada, 27 | foo(a + b) = foo(a) * bar(b) + bar(a) * foo(b) 28 | bar(a + b) = bar(a) * bar(b) - foo(a) * foo(b) 29 | 30 | Yada, yada, 31 | yada, yada. 32 | 33 | Yada, yada, 34 | yada, yada. 35 | */ 36 | D"); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tests/functional/objc/methods.d: -------------------------------------------------------------------------------- 1 | extern (Objective-C): 2 | 3 | class Foo 4 | { 5 | static void classMethod () @selector("classMethod"); 6 | void instanceMethod () @selector("instanceMethod"); 7 | static void initialize () @selector("initialize"); 8 | @property static ObjcObject new_ () @selector("new"); 9 | @property static Class class () @selector("class"); 10 | @property ObjcObject init () @selector("init"); 11 | static ObjcObject allocWithZone (NSZone* zone) @selector("allocWithZone:"); 12 | IMP methodForSelector (SEL aSelector) @selector("methodForSelector:"); 13 | @property static NSInteger version_ () @selector("version"); 14 | @property static void version_ (NSInteger aVersion) @selector("setVersion:"); 15 | @property static NSUInteger NSUIntegerTest () @selector("NSUIntegerTest"); 16 | ObjcObject performSelector (SEL aSelector, ObjcObject object) @selector("performSelector:withObject:"); 17 | } 18 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue116.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jan 26, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Options; 10 | 11 | // Fix 116: Option --space-after-function-name doesn't work with function 12 | // pointer syntax. 13 | unittest 14 | { 15 | Options options; 16 | options.spaceAfterFunctionName = false; 17 | 18 | assertTranslates( 19 | q"C 20 | int foo(void); 21 | 22 | typedef int (*Fun0)(void); 23 | typedef int (*Fun1)(int (*param)(void)); 24 | 25 | struct Foo { 26 | int (*bar)(void); 27 | }; 28 | C", 29 | q"D 30 | extern (C): 31 | 32 | int foo(); 33 | 34 | alias Fun0 = int function(); 35 | alias Fun1 = int function(int function() param); 36 | 37 | struct Foo 38 | { 39 | int function() bar; 40 | } 41 | D", options); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue102.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Dec 17, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 102: Regression: usage of typedefs within structs. 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | typedef struct _ProtobufCMethodDescriptor ProtobufCMethodDescriptor; 15 | 16 | struct _ProtobufCMethodDescriptor 17 | { 18 | const char *name; 19 | const ProtobufCMethodDescriptor *input; 20 | const ProtobufCMethodDescriptor *output; 21 | }; 22 | C", 23 | q"D 24 | extern (C): 25 | 26 | alias ProtobufCMethodDescriptor = _ProtobufCMethodDescriptor; 27 | 28 | struct _ProtobufCMethodDescriptor 29 | { 30 | const(char)* name; 31 | const(ProtobufCMethodDescriptor)* input; 32 | const(ProtobufCMethodDescriptor)* output; 33 | } 34 | D"); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /resources/__stddef_max_align_t.h: -------------------------------------------------------------------------------- 1 | /*===---- __stddef_max_align_t.h - Definition of max_align_t for modules ---=== 2 | * 3 | * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | * See https://llvm.org/LICENSE.txt for license information. 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | * 7 | *===-----------------------------------------------------------------------=== 8 | */ 9 | 10 | #ifndef __CLANG_MAX_ALIGN_T_DEFINED 11 | #define __CLANG_MAX_ALIGN_T_DEFINED 12 | 13 | #if defined(_MSC_VER) 14 | typedef double max_align_t; 15 | #elif defined(__APPLE__) 16 | typedef long double max_align_t; 17 | #else 18 | // Define 'max_align_t' to match the GCC definition. 19 | typedef struct { 20 | long long __clang_max_align_nonce1 21 | __attribute__((__aligned__(__alignof__(long long)))); 22 | long double __clang_max_align_nonce2 23 | __attribute__((__aligned__(__alignof__(long double)))); 24 | } max_align_t; 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue140.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: June 04, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Options; 10 | 11 | // Fix 140: On enums and scope 12 | unittest 13 | { 14 | Options options; 15 | options.aliasEnumMembers = true; 16 | 17 | assertTranslates(q"C 18 | typedef enum fe_delivery_system { 19 | SYS_UNDEFINED, 20 | SYS_DVBC_ANNEX_A, 21 | } fe_delivery_system_t; 22 | C", 23 | q"D 24 | extern (C): 25 | 26 | enum fe_delivery_system 27 | { 28 | SYS_UNDEFINED = 0, 29 | SYS_DVBC_ANNEX_A = 1 30 | } 31 | 32 | alias SYS_UNDEFINED = fe_delivery_system.SYS_UNDEFINED; 33 | alias SYS_DVBC_ANNEX_A = fe_delivery_system.SYS_DVBC_ANNEX_A; 34 | 35 | alias fe_delivery_system_t = fe_delivery_system; 36 | D", 37 | options); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue10.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Aug 03, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 10: Embedded struct not generated. 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | struct info { 15 | long remote_ip; 16 | int remote_port; 17 | int is_ssl; 18 | void *user_data; 19 | 20 | struct mg_header { 21 | const char *name; 22 | const char *value; 23 | } headers[64]; 24 | }; 25 | C", 26 | q"D 27 | import core.stdc.config; 28 | 29 | extern (C): 30 | 31 | struct info 32 | { 33 | c_long remote_ip; 34 | int remote_port; 35 | int is_ssl; 36 | void* user_data; 37 | 38 | struct mg_header 39 | { 40 | const(char)* name; 41 | const(char)* value; 42 | } 43 | 44 | mg_header[64] headers; 45 | } 46 | D"); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /dstep/translator/objc/Category.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2012 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Aug 6, 2012 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.translator.objc.Category; 8 | 9 | import clang.Cursor; 10 | import clang.Type; 11 | 12 | import dstep.translator.Declaration; 13 | import dstep.translator.objc.ObjcInterface; 14 | import dstep.translator.Output; 15 | import dstep.translator.Translator; 16 | 17 | class Category : ObjcInterface!(ClassExtensionData) 18 | { 19 | this (Cursor cursor, Cursor parent, Translator translator) 20 | { 21 | super(cursor, parent, translator); 22 | } 23 | 24 | protected override string[] collectInterfaces (ObjcCursor cursor) 25 | { 26 | auto interfaces = super.collectInterfaces(cursor); 27 | auto category = translateIdentifier(cursor.category.spelling); 28 | 29 | return category ~ interfaces; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue203.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 29, 2018 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | #define IsUpper(c) ((0101 <= (c) && (c) <= 0132)) 15 | #define IsLower(c) ((0141 <= (c) && (c) <= 0172)) 16 | #define ToLower(c) (IsUpper(c) ? (c) - 0101 + 0141 : (c)) 17 | C", q"D 18 | extern (C): 19 | 20 | extern (D) auto IsUpper(T)(auto ref T c) 21 | { 22 | import std.conv : octal; 23 | 24 | return (octal!101 <= c && c <= octal!132); 25 | } 26 | 27 | extern (D) auto IsLower(T)(auto ref T c) 28 | { 29 | import std.conv : octal; 30 | 31 | return (octal!141 <= c && c <= octal!172); 32 | } 33 | 34 | extern (D) auto ToLower(T)(auto ref T c) 35 | { 36 | import std.conv : octal; 37 | 38 | return IsUpper(c) ? c - octal!101 + octal!141 : c; 39 | } 40 | D"); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /todo.taskpaper: -------------------------------------------------------------------------------- 1 | - Multiple input files 2 | - Framework as input file 3 | - Add module declaration 4 | - Option for specifying before and after code 5 | - Formatting of imports @done(2012-06-29) 6 | - Option for specifying package 7 | - Compile on Windows @done(2013-11-02) 8 | - Compile on Linux @done(2012-07-28) 9 | C: 10 | - Anonymous structs @done(2012-06-30) 11 | - Self includes 12 | - Hardcode the translation of some typedefs @done(2012-06-30) 13 | - Out of order typedefs of structs @done(2013-11-02) 14 | - Bitfields 15 | - Non-standard extensions 16 | 17 | Preprocessor: 18 | - Better handling of includes 19 | - Constants - #define foo 1 20 | - Versions - #if __APPLE__ 21 | - Function macros - #define foo (a, b) a + b 22 | - Syntactic macros - #define foo (a, b) a##b 23 | Objective-C: 24 | - Protocols @done(2012-08-06) 25 | - Properties @done(2012-08-05) 26 | - Blocks 27 | - Categories @done(2012-08-06) 28 | - Actions 29 | - Outlets 30 | - Selectors 31 | - Constructors 32 | -------------------------------------------------------------------------------- /clang/c/Platform.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides platform specific macros (dllimport, deprecated, ...) *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.Platform; 15 | 16 | extern (C): 17 | 18 | /* Windows DLL import/export. */ 19 | 20 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue204.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 29, 2018 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | #include 15 | 16 | typedef enum _ValueBinding { 17 | ValueBindingWeak, 18 | ValueBindingEnd = INT_MAX 19 | } ValueBinding; 20 | C", 21 | q"D 22 | import core.stdc.limits; 23 | 24 | extern (C): 25 | 26 | enum _ValueBinding 27 | { 28 | ValueBindingWeak = 0, 29 | ValueBindingEnd = INT_MAX 30 | } 31 | 32 | alias ValueBinding = _ValueBinding; 33 | D"); 34 | 35 | version (linux) { 36 | assertTranslates( 37 | q"C 38 | #include 39 | 40 | void* DirCacheLoadFile (const char *cache_file, struct stat *file_stat); 41 | C", 42 | q"D 43 | import core.sys.posix.sys.stat; 44 | 45 | extern (C): 46 | 47 | void* DirCacheLoadFile (const(char)* cache_file, stat_t* file_stat); 48 | D"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/functional/clang-c/Platform.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides platform specific macros (dllimport, deprecated, ...) *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.platform; 15 | 16 | extern (C): 17 | 18 | /* MSVC DLL import/export. */ 19 | 20 | -------------------------------------------------------------------------------- /resources/stdbool.h: -------------------------------------------------------------------------------- 1 | /*===---- stdbool.h - Standard header for booleans -------------------------=== 2 | * 3 | * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | * See https://llvm.org/LICENSE.txt for license information. 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | * 7 | *===-----------------------------------------------------------------------=== 8 | */ 9 | 10 | #ifndef __STDBOOL_H 11 | #define __STDBOOL_H 12 | 13 | #define __bool_true_false_are_defined 1 14 | 15 | #if __STDC_VERSION__ > 201710L 16 | /* FIXME: We should be issuing a deprecation warning here, but cannot yet due 17 | * to system headers which include this header file unconditionally. 18 | */ 19 | #elif !defined(__cplusplus) 20 | #define bool _Bool 21 | #define true 1 22 | #define false 0 23 | #elif defined(__GNUC__) && !defined(__STRICT_ANSI__) 24 | /* Define _Bool as a GNU extension. */ 25 | #define _Bool bool 26 | #if __cplusplus < 201103L 27 | /* For C++98, define bool, false, true as a GNU extension. */ 28 | #define bool bool 29 | #define false false 30 | #define true true 31 | #endif 32 | #endif 33 | 34 | #endif /* __STDBOOL_H */ 35 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue202.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: October 03, 2018 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | unittest 11 | { 12 | assertTranslates( 13 | q"C 14 | typedef struct 15 | { 16 | } BOARDINFO, *PBOARDINFO; 17 | C", q"D 18 | extern (C): 19 | 20 | struct BOARDINFO 21 | { 22 | } 23 | 24 | alias PBOARDINFO = BOARDINFO*; 25 | D"); 26 | 27 | assertTranslates( 28 | q"C 29 | typedef struct 30 | { 31 | char SerNo[12]; 32 | char ID[20]; 33 | char Version[10]; 34 | char Date[12]; 35 | unsigned char Select; 36 | unsigned char Type; 37 | char Reserved[8]; 38 | } BOARDINFO, *PBOARDINFO; 39 | C", q"D 40 | extern (C): 41 | 42 | struct BOARDINFO 43 | { 44 | char[12] SerNo; 45 | char[20] ID; 46 | char[10] Version; 47 | char[12] Date; 48 | ubyte Select; 49 | ubyte Type; 50 | char[8] Reserved; 51 | } 52 | 53 | alias PBOARDINFO = BOARDINFO*; 54 | D"); 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /library_test.d: -------------------------------------------------------------------------------- 1 | import std.algorithm : filter; 2 | import std.array : array; 3 | import std.stdio; 4 | import std.process : spawnProcess, Config, wait; 5 | 6 | @safe: 7 | 8 | void main() 9 | { 10 | executeCommand(dubShellCommand()); 11 | } 12 | 13 | string[] dubShellCommand() pure nothrow 14 | { 15 | return (["dub", "run", "--verror"] ~ dubArch) 16 | .filter!(e => e.length > 0) 17 | .array; 18 | } 19 | 20 | void executeCommand(const string[] args ...) 21 | { 22 | import std.process : spawnProcess, wait; 23 | import std.array : join; 24 | 25 | immutable string[string] env; 26 | immutable config = Config.none; 27 | immutable workDir = "tests/functional/test_package"; 28 | 29 | 30 | if (spawnProcess(args, env, config, workDir).wait() != 0) 31 | throw new Exception("Failed to execute command: " ~ args.join(' ')); 32 | } 33 | 34 | string dubArch() pure nothrow 35 | { 36 | version (Win64) 37 | return "--arch=x86_64"; 38 | 39 | else version (Win32) 40 | { 41 | version (DigitalMars) 42 | return "--arch=x86_mscoff"; 43 | else 44 | return "--arch=x86"; 45 | } 46 | 47 | else 48 | return ""; 49 | } 50 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue160.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: August 26, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 160: Translating typedef of function pointer doesn't take line length 11 | // into consideration 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | typedef struct { } CXFile; 16 | typedef struct { } CXSourceLocation; 17 | typedef struct { } CXClientData; 18 | 19 | typedef void (*CXInclusionVisitor)(CXFile included_file, 20 | CXSourceLocation* inclusion_stack, 21 | unsigned include_len, 22 | CXClientData client_data); 23 | C", 24 | q"D 25 | extern (C): 26 | 27 | struct CXFile 28 | { 29 | } 30 | 31 | struct CXSourceLocation 32 | { 33 | } 34 | 35 | struct CXClientData 36 | { 37 | } 38 | 39 | alias CXInclusionVisitor = void function ( 40 | CXFile included_file, 41 | CXSourceLocation* inclusion_stack, 42 | uint include_len, 43 | CXClientData client_data); 44 | D"); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /clang/c/FatalErrorHandler.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | \*===----------------------------------------------------------------------===*/ 9 | 10 | module clang.c.FatalErrorHandler; 11 | 12 | extern (C): 13 | 14 | /** 15 | * Installs error handler that prints error message to stderr and calls abort(). 16 | * Replaces currently installed error handler (if any). 17 | */ 18 | void clang_install_aborting_llvm_fatal_error_handler(); 19 | 20 | /** 21 | * Removes currently installed error handler (if any). 22 | * If no error handler is intalled, the default strategy is to print error 23 | * message to stderr and call exit(1). 24 | */ 25 | void clang_uninstall_llvm_fatal_error_handler(); 26 | 27 | -------------------------------------------------------------------------------- /resources/stdarg.h: -------------------------------------------------------------------------------- 1 | /*===---- stdarg.h - Variable argument handling ----------------------------=== 2 | * 3 | * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | * See https://llvm.org/LICENSE.txt for license information. 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | * 7 | *===-----------------------------------------------------------------------=== 8 | */ 9 | 10 | #ifndef __STDARG_H 11 | #define __STDARG_H 12 | 13 | #ifndef _VA_LIST 14 | typedef __builtin_va_list va_list; 15 | #define _VA_LIST 16 | #endif 17 | #define va_start(ap, param) __builtin_va_start(ap, param) 18 | #define va_end(ap) __builtin_va_end(ap) 19 | #define va_arg(ap, type) __builtin_va_arg(ap, type) 20 | 21 | /* GCC always defines __va_copy, but does not define va_copy unless in c99 mode 22 | * or -ansi is not specified, since it was not part of C90. 23 | */ 24 | #define __va_copy(d,s) __builtin_va_copy(d,s) 25 | 26 | #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L || !defined(__STRICT_ANSI__) 27 | #define va_copy(dest, src) __builtin_va_copy(dest, src) 28 | #endif 29 | 30 | #ifndef __GNUC_VA_LIST 31 | #define __GNUC_VA_LIST 1 32 | typedef __builtin_va_list __gnuc_va_list; 33 | #endif 34 | 35 | #endif /* __STDARG_H */ 36 | -------------------------------------------------------------------------------- /tools/generate_version.d: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dub 2 | 3 | /+ dub.sdl: 4 | name "generate_version" 5 | +/ 6 | 7 | import std.file : exists, mkdirRecurse, readText, write; 8 | import std.exception : enforce; 9 | import std.path : buildPath, buildNormalizedPath, dirName; 10 | import std.process : execute; 11 | import std.string : strip; 12 | 13 | enum rootDirectory = __FILE_FULL_PATH__.dirName.buildNormalizedPath(".."); 14 | enum outputDirectory = rootDirectory.buildPath("resources"); 15 | enum versionFile = "VERSION"; 16 | 17 | void main() 18 | { 19 | mkdirRecurse(outputDirectory); 20 | 21 | outputDirectory 22 | .buildPath(versionFile) 23 | .updateIfChanged(generateVersion); 24 | } 25 | 26 | string generateVersion() 27 | { 28 | const args = [ 29 | "git", 30 | "-C", rootDirectory, 31 | "describe", 32 | "--tags", 33 | "--always" 34 | ]; 35 | 36 | const result = execute(args); 37 | enforce(result.status == 0, "Failed to execute 'git describe'"); 38 | 39 | return result.output.strip; 40 | } 41 | 42 | void updateIfChanged(const string path, const string content) 43 | { 44 | const existingContent = path.exists ? path.readText : ""; 45 | 46 | if (content != existingContent) 47 | write(path, content); 48 | } 49 | -------------------------------------------------------------------------------- /tests/unit/CommentIndexTests.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: May 20, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import std.stdio; 8 | import Common; 9 | import dstep.translator.CommentIndex; 10 | 11 | unittest 12 | { 13 | string test = q"C 14 | 15 | /* This is comment. */ 16 | 17 | /* This is another comment. */ 18 | 19 | #define FOO 64 20 | #define BAR 128 21 | 22 | /* As most comments this comment is obsolete. 23 | BAZ is 255. */ 24 | 25 | #define BAZ 256 26 | 27 | struct Foo { 28 | int a; 29 | int b; 30 | }; 31 | 32 | /* Another lengthy comment. 33 | Foo bar baz. 34 | Foo bar baz. 35 | Foo bar baz. 36 | Foo bar baz. 37 | Foo bar baz. 38 | 39 | */ 40 | 41 | /* */ 42 | 43 | C"; 44 | 45 | auto translUnit = makeTranslationUnit(test); 46 | 47 | auto commentIndex = new CommentIndex(translUnit); 48 | 49 | auto full = commentIndex.queryComments(0, cast(uint) test.length); 50 | 51 | assert(full.length == 5); 52 | 53 | auto alpha = commentIndex.queryComments(1, 55); 54 | 55 | assert(alpha.length == 2); 56 | assert(alpha[0].content == "/* This is comment. */"); 57 | assert(alpha[1].content == "/* This is another comment. */"); 58 | } 59 | -------------------------------------------------------------------------------- /tools/build_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | app_name="dstep" 6 | target_dir="bin" 7 | target_path="$target_dir/$app_name" 8 | 9 | function configure { 10 | local os=$(os) 11 | local default_flags="--llvm-path tmp/clang" 12 | 13 | if [ "$os" = 'macos' ]; then 14 | ./configure --statically-link-clang $default_flags 15 | elif [ "$os" = 'linux' ]; then 16 | ./configure --statically-link-binary $default_flags 17 | elif [ "$os" = 'freebsd' ]; then 18 | ./configure --statically-link-binary $default_flags 19 | else 20 | echo "Platform not supported: $os" 21 | exit 1 22 | fi 23 | } 24 | 25 | function build { 26 | dub build -b release --verror 27 | strip "$target_path" 28 | } 29 | 30 | function test_dstep { 31 | dub -c test-functional --verror 32 | } 33 | 34 | function version { 35 | "$target_path" --version 36 | } 37 | 38 | function arch { 39 | uname -m 40 | } 41 | 42 | function os { 43 | os=$(uname | tr '[:upper:]' '[:lower:]') 44 | [ $os = 'darwin' ] && echo 'macos' || echo $os 45 | } 46 | 47 | function release_name { 48 | local release_name="$app_name-$(version)-$(os)" 49 | 50 | if [ "$(os)" = 'macos' ]; then 51 | echo "$release_name" 52 | else 53 | echo "$release_name-$(arch)" 54 | fi 55 | } 56 | 57 | function archive { 58 | tar Jcf "$(release_name)".tar.xz -C "$target_dir" "$app_name" 59 | } 60 | 61 | configure 62 | build 63 | test_dstep 64 | archive 65 | -------------------------------------------------------------------------------- /dstep/translator/Declaration.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Jan 29, 2012 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.translator.Declaration; 8 | 9 | import clang.Cursor; 10 | 11 | import dstep.translator.Translator; 12 | import dstep.translator.Output; 13 | import dstep.translator.Util; 14 | 15 | abstract class Declaration 16 | { 17 | protected 18 | { 19 | Cursor cursor; 20 | Cursor parent; 21 | 22 | Translator translator; 23 | } 24 | 25 | template Constructors () 26 | { 27 | import clang.Cursor; 28 | import dstep.translator.Output; 29 | 30 | this (Cursor cursor, Cursor parent, Translator translator) 31 | { 32 | super(cursor, parent, translator); 33 | } 34 | } 35 | 36 | this (Cursor cursor, Cursor parent, Translator translator) 37 | { 38 | this.cursor = cursor; 39 | this.parent = parent; 40 | this.translator = translator; 41 | } 42 | 43 | abstract void translate (Output output); 44 | 45 | @property string spelling () 46 | { 47 | auto name = cursor.spelling; 48 | return !name.isUnnamed && (name.length || parent.isEmpty) ? name : translator.context.generateAnonymousName(cursor); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue166.d: -------------------------------------------------------------------------------- 1 | import Common; 2 | 3 | @("issue #166 - translate record with name from macro") 4 | unittest 5 | { 6 | assertTranslates( 7 | q"C 8 | 9 | #define __FSID_T_TYPE struct { int __val[2]; } 10 | typedef __FSID_T_TYPE __fsid_t; 11 | typedef __fsid_t fsid_t; 12 | 13 | C", 14 | q"D 15 | extern (C): 16 | 17 | struct __fsid_t 18 | { 19 | int[2] __val; 20 | } 21 | 22 | alias fsid_t = __fsid_t; 23 | 24 | D"); 25 | 26 | } 27 | 28 | 29 | @("issue #166 - translate record with name from macro in a literal macro") 30 | unittest 31 | { 32 | assertTranslates( 33 | q"C 34 | #define FOO 2 35 | #define __FSID_T_TYPE struct { int __val[FOO]; } 36 | typedef __FSID_T_TYPE __fsid_t; 37 | typedef __fsid_t fsid_t; 38 | C", 39 | q"D 40 | extern (C): 41 | 42 | enum FOO = 2; 43 | 44 | struct __fsid_t 45 | { 46 | int[FOO] __val; 47 | } 48 | 49 | alias fsid_t = __fsid_t; 50 | 51 | D"); 52 | 53 | } 54 | 55 | 56 | @("issue #166 - translate record with name from macro in a macro in a macro") 57 | unittest 58 | { 59 | assertTranslates( 60 | q"C 61 | #define FOO 2 62 | #define BAR FOO 63 | #define __FSID_T_TYPE struct { int __val[BAR]; } 64 | typedef __FSID_T_TYPE __fsid_t; 65 | typedef __fsid_t fsid_t; 66 | C", 67 | q"D 68 | extern (C): 69 | 70 | enum FOO = 2; 71 | enum BAR = FOO; 72 | 73 | struct __fsid_t 74 | { 75 | int[BAR] __val; 76 | } 77 | 78 | alias fsid_t = __fsid_t; 79 | 80 | D"); 81 | 82 | } 83 | -------------------------------------------------------------------------------- /clang/Token.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Feb 14, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.Token; 8 | 9 | import std.conv : to; 10 | import std.typecons; 11 | public import std.range.primitives : empty, front, back; 12 | 13 | import clang.c.Index; 14 | import clang.SourceLocation; 15 | import clang.SourceRange; 16 | import clang.Type; 17 | import clang.Util; 18 | import clang.Visitor; 19 | import clang.Cursor; 20 | 21 | enum TokenKind 22 | { 23 | punctuation = CXTokenKind.punctuation, 24 | keyword = CXTokenKind.keyword, 25 | identifier = CXTokenKind.identifier, 26 | literal = CXTokenKind.literal, 27 | comment = CXTokenKind.comment, 28 | } 29 | 30 | TokenKind toD(CXTokenKind kind) 31 | { 32 | return cast(TokenKind) kind; 33 | } 34 | 35 | struct Token 36 | { 37 | TokenKind kind; 38 | string spelling; 39 | SourceRange extent; 40 | 41 | @property SourceLocation location() 42 | { 43 | return extent.start; 44 | } 45 | 46 | @property string toString() const 47 | { 48 | import std.format: format; 49 | return format("Token(kind = %s, spelling = %s)", kind, spelling); 50 | } 51 | } 52 | 53 | SourceRange extent(Token[] tokens) 54 | { 55 | if (!tokens.empty) 56 | return SourceRange( 57 | tokens.front.extent.start, 58 | tokens.back.extent.end); 59 | else 60 | return SourceRange.empty; 61 | } 62 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Code Style for Contributors 2 | 3 | * Use camelCase for functions and PascalCase for types. 4 | * Do not use tabs, indent code with 4 spaces. 5 | * If possible, a line of code should be at most 80 characters long. 6 | * Put a space between foreach, if, while etc. and the opening parenthesis. 7 | * Prefer to not include an empty set of parentheses in cases where there are only template parameters. 8 | 9 | ```d 10 | auto good = foo.map!predicate; 11 | auto bad = foo.map!predicate(); 12 | ``` 13 | 14 | * Add spaces around operators. 15 | ```d 16 | while (good && correct) 17 | perfect[1 .. $] = excellent[1 .. $]; 18 | 19 | while (bad&&wrong) 20 | poor[1..$] = inferior[1..$]; 21 | ``` 22 | 23 | * Do not use braces for single-line statements. 24 | ```d 25 | while (true) 26 | good(); 27 | 28 | while (true) 29 | { 30 | wrong(); 31 | } 32 | ``` 33 | 34 | * Do not leave white-spaces at the end of line. 35 | * Do not put extra newlines at the end of file. 36 | * Use type inference, if possible. 37 | * Prefer to use UFCS for algorithm functions. 38 | * Do not use UFCS for `std.format.format`. 39 | * Prefer `foreach` over plain old `for`: 40 | 41 | ```d 42 | for (size_t bad = 0; bad < length; ++bad) 43 | { 44 | ... 45 | } 46 | 47 | foreach (good; 0 .. length) 48 | { 49 | ... 50 | } 51 | ``` 52 | 53 | * Prefer using algorithms over `foreach`. 54 | * Do not put spaces between `cast` and the opening parenthesis (`cast(Good)`). 55 | * Do not put a newline between the documentation and the symbol it's attached to. 56 | * For single-line ddocs use `///`. 57 | * For multi-line ddocs use 58 | ```d 59 | /** 60 | * 61 | */ 62 | ``` 63 | -------------------------------------------------------------------------------- /tests/unit/IncludeHandlerTests.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: October 07, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import Common; 8 | 9 | import clang.c.Index; 10 | import clang.Compiler; 11 | import clang.Index; 12 | import clang.TranslationUnit; 13 | import clang.Util; 14 | 15 | import dstep.translator.HeaderIndex; 16 | 17 | // Include standard library module when the dependency is used in macro. 18 | unittest 19 | { 20 | assertTranslates( 21 | q"C 22 | #include 23 | 24 | #define FOO RAND_MAX 25 | C", 26 | q"D 27 | import core.stdc.stdlib; 28 | 29 | extern (C): 30 | 31 | enum FOO = RAND_MAX; 32 | D"); 33 | 34 | assertTranslates( 35 | q"C 36 | #include 37 | 38 | #define FOO INT_MAX 39 | C", 40 | q"D 41 | import core.stdc.limits; 42 | 43 | extern (C): 44 | 45 | enum FOO = INT_MAX; 46 | D"); 47 | 48 | assertTranslates( 49 | q"C 50 | #include 51 | 52 | #define FOO UINT32_MAX 53 | C", 54 | q"D 55 | import core.stdc.stdint; 56 | 57 | extern (C): 58 | 59 | enum FOO = UINT32_MAX; 60 | D"); 61 | 62 | } 63 | 64 | version(Posix) 65 | { 66 | 67 | unittest 68 | { 69 | // TODO: Following requires an improvement as the definition of _IOR in 70 | // core.sys.posix.sys.ioctl has different interface 71 | // (it takes two arguments). 72 | assertTranslates(q"C 73 | #include 74 | 75 | #define FOO _IOR('o', 61, int) 76 | C", 77 | q"D 78 | import core.sys.posix.sys.ioctl; 79 | 80 | extern (C): 81 | 82 | enum FOO = _IOR!int('o', 61); 83 | D"); 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /tests/functional/clang-c/Platform.h: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides platform specific macros (dllimport, deprecated, ...) *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | #ifndef LLVM_CLANG_C_PLATFORM_H 15 | #define LLVM_CLANG_C_PLATFORM_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /* MSVC DLL import/export. */ 22 | #ifdef _MSC_VER 23 | #ifdef _CINDEX_LIB_ 24 | #define CINDEX_LINKAGE __declspec(dllexport) 25 | #else 26 | #define CINDEX_LINKAGE __declspec(dllimport) 27 | #endif 28 | #else 29 | #define CINDEX_LINKAGE 30 | #endif 31 | 32 | #ifdef __GNUC__ 33 | #define CINDEX_DEPRECATED __attribute__((deprecated)) 34 | #else 35 | #ifdef _MSC_VER 36 | #define CINDEX_DEPRECATED __declspec(deprecated) 37 | #else 38 | #define CINDEX_DEPRECATED 39 | #endif 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /ci.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Environment variables: 4 | # DSTEP_COMPILER: the compiler to build with 5 | # DSTEP_LLVM_VERSION: the version of LLVM to link with 6 | # DSTEP_TARGET_TRIPLE: the target triple to build for 7 | # DSTEP_RELEASE_PLATFORM: the name of the platform 8 | 9 | set -exo pipefail 10 | 11 | export MACOSX_DEPLOYMENT_TARGET=10.9 12 | 13 | download() { 14 | curl --retry 3 -fsS "$1" 15 | } 16 | 17 | d_compiler() { 18 | echo "$DSTEP_COMPILER" | \ 19 | sed 's/-latest//' | \ 20 | sed 's/dmd-master/dmd-nightly/' 21 | } 22 | 23 | install_d_compiler() { 24 | download https://dlang.org/d-keyring.gpg | gpg --import /dev/stdin 25 | source $(download https://dlang.org/install.sh | bash -s "$(d_compiler)" -a) 26 | } 27 | 28 | configure() { 29 | ./configure --llvm-path "llvm-$DSTEP_LLVM_VERSION" --statically-link-clang 30 | } 31 | 32 | target_triple_arg() { 33 | if echo "$(d_compiler)" | grep -i -q ldc; then 34 | echo "--mtriple=$DSTEP_TARGET_TRIPLE" 35 | else 36 | echo "-target=$DSTEP_TARGET_TRIPLE" 37 | fi 38 | } 39 | 40 | run_tests() { 41 | DFLAGS="$(target_triple_arg)" dub test --verror 42 | } 43 | 44 | release() { 45 | DFLAGS="$(target_triple_arg)" dub build -b release --verror 46 | strip "$target_path"* 47 | archive 48 | } 49 | 50 | version() { 51 | "$target_path"* --version 52 | } 53 | 54 | release_name() { 55 | echo "$app_name-$(version)-$DSTEP_RELEASE_PLATFORM" 56 | } 57 | 58 | archive() { 59 | if uname | grep -i -q mingw; then 60 | 7z a "$(release_name).7z" "$target_path"* 61 | else 62 | tar Jcf "$(release_name).tar.xz" -C "$target_dir" "$app_name" 63 | fi 64 | } 65 | 66 | app_name="dstep" 67 | target_dir="bin" 68 | target_path="$target_dir/$app_name" 69 | 70 | install_d_compiler 71 | configure 72 | 73 | case "$1" in 74 | 'test') run_tests ;; 75 | 'release') release ;; 76 | esac 77 | -------------------------------------------------------------------------------- /clang/c/Rewrite.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/Rewrite.h - C CXRewriter --------------------------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*/ 9 | 10 | module clang.c.Rewrite; 11 | 12 | public import clang.c.Index; 13 | 14 | extern (C): 15 | 16 | alias CXRewriter = void*; 17 | 18 | /** 19 | * Create CXRewriter. 20 | */ 21 | CXRewriter clang_CXRewriter_create(CXTranslationUnit TU); 22 | 23 | /** 24 | * Insert the specified string at the specified location in the original buffer. 25 | */ 26 | void clang_CXRewriter_insertTextBefore( 27 | CXRewriter Rew, 28 | CXSourceLocation Loc, 29 | const(char)* Insert); 30 | 31 | /** 32 | * Replace the specified range of characters in the input with the specified 33 | * replacement. 34 | */ 35 | void clang_CXRewriter_replaceText( 36 | CXRewriter Rew, 37 | CXSourceRange ToBeReplaced, 38 | const(char)* Replacement); 39 | 40 | /** 41 | * Remove the specified range. 42 | */ 43 | void clang_CXRewriter_removeText(CXRewriter Rew, CXSourceRange ToBeRemoved); 44 | 45 | /** 46 | * Save all changed files to disk. 47 | * Returns 1 if any files were not saved successfully, returns 0 otherwise. 48 | */ 49 | int clang_CXRewriter_overwriteChangedFiles(CXRewriter Rew); 50 | 51 | /** 52 | * Write out rewritten version of the main file to stdout. 53 | */ 54 | void clang_CXRewriter_writeMainFileToStdOut(CXRewriter Rew); 55 | 56 | /** 57 | * Free the given CXRewriter. 58 | */ 59 | void clang_CXRewriter_dispose(CXRewriter Rew); 60 | 61 | -------------------------------------------------------------------------------- /clang/SourceRange.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Feb 14, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.SourceRange; 8 | 9 | import std.conv; 10 | import clang.c.Index; 11 | import clang.SourceLocation; 12 | import clang.Util; 13 | 14 | struct SourceRange 15 | { 16 | mixin CX; 17 | 18 | this(CXSourceRange cx) 19 | { 20 | this.cx = cx; 21 | } 22 | 23 | @property static SourceRange empty() 24 | { 25 | return SourceRange(clang_getNullRange()); 26 | } 27 | 28 | @property bool isEmpty() 29 | { 30 | return clang_Range_isNull(cx) != 0; 31 | } 32 | 33 | this(SourceLocation start, SourceLocation end) 34 | { 35 | cx = clang_getRange(start.cx, end.cx); 36 | } 37 | 38 | @property SourceLocation start() const 39 | { 40 | return SourceLocation(clang_getRangeStart(cx)); 41 | } 42 | 43 | @property SourceLocation end() const 44 | { 45 | return SourceLocation(clang_getRangeEnd(cx)); 46 | } 47 | 48 | @property bool isMultiline() const 49 | { 50 | return start.line != end.line; 51 | } 52 | 53 | @property string path() const 54 | { 55 | return start.path; 56 | } 57 | 58 | @property string toString() const 59 | { 60 | import std.format: format; 61 | return format("SourceRange(start = %s, end = %s)", start, end); 62 | } 63 | } 64 | 65 | bool intersects(in SourceRange a, in SourceRange b) 66 | { 67 | return a.path == b.path && 68 | (a.start.offset <= b.start.offset && b.start.offset < a.end.offset) || 69 | (a.start.offset < b.end.offset && b.end.offset <= a.end.offset); 70 | } 71 | 72 | bool contains(in SourceRange a, in SourceRange b) 73 | { 74 | return a.path == b.path && 75 | a.start.offset <= b.start.offset && b.end.offset <= a.end.offset; 76 | } 77 | -------------------------------------------------------------------------------- /clang/c/CXErrorCode.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides the CXErrorCode enumerators. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.CXErrorCode; 15 | 16 | extern (C): 17 | 18 | /** 19 | * Error codes returned by libclang routines. 20 | * 21 | * Zero (\c CXError_Success) is the only error code indicating success. Other 22 | * error codes, including not yet assigned non-zero values, indicate errors. 23 | */ 24 | enum CXErrorCode 25 | { 26 | /** 27 | * No error. 28 | */ 29 | success = 0, 30 | 31 | /** 32 | * A generic error code, no further details are available. 33 | * 34 | * Errors of this kind can get their own specific error codes in future 35 | * libclang versions. 36 | */ 37 | failure = 1, 38 | 39 | /** 40 | * libclang crashed while performing the requested operation. 41 | */ 42 | crashed = 2, 43 | 44 | /** 45 | * The function detected that the arguments violate the function 46 | * contract. 47 | */ 48 | invalidArguments = 3, 49 | 50 | /** 51 | * An AST deserialization error has occurred. 52 | */ 53 | astReadError = 4 54 | } 55 | -------------------------------------------------------------------------------- /clang/c/CXString.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides the interface to C Index strings. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.CXString; 15 | 16 | extern (C): 17 | 18 | /** 19 | * \defgroup CINDEX_STRING String manipulation routines 20 | * \ingroup CINDEX 21 | * 22 | * @{ 23 | */ 24 | 25 | /** 26 | * A character string. 27 | * 28 | * The \c CXString type is used to return strings from the interface when 29 | * the ownership of that string might differ from one call to the next. 30 | * Use \c clang_getCString() to retrieve the string data and, once finished 31 | * with the string data, call \c clang_disposeString() to free the string. 32 | */ 33 | struct CXString 34 | { 35 | const(void)* data; 36 | uint private_flags; 37 | } 38 | 39 | struct CXStringSet 40 | { 41 | CXString* Strings; 42 | uint Count; 43 | } 44 | 45 | /** 46 | * Retrieve the character data associated with the given string. 47 | */ 48 | const(char)* clang_getCString(CXString string); 49 | 50 | /** 51 | * Free the given string. 52 | */ 53 | void clang_disposeString(CXString string); 54 | 55 | /** 56 | * Free the given string set. 57 | */ 58 | void clang_disposeStringSet(CXStringSet* set); 59 | 60 | /** 61 | * @} 62 | */ 63 | 64 | -------------------------------------------------------------------------------- /tests/functional/clang-c/CXErrorCode.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides the CXErrorCode enumerators. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.cx_error_code; 15 | 16 | extern (C): 17 | 18 | /** 19 | * \brief Error codes returned by libclang routines. 20 | * 21 | * Zero (\c CXError_Success) is the only error code indicating success. Other 22 | * error codes, including not yet assigned non-zero values, indicate errors. 23 | */ 24 | enum CXErrorCode 25 | { 26 | /** 27 | * \brief No error. 28 | */ 29 | CXError_Success = 0, 30 | 31 | /** 32 | * \brief A generic error code, no further details are available. 33 | * 34 | * Errors of this kind can get their own specific error codes in future 35 | * libclang versions. 36 | */ 37 | CXError_Failure = 1, 38 | 39 | /** 40 | * \brief libclang crashed while performing the requested operation. 41 | */ 42 | CXError_Crashed = 2, 43 | 44 | /** 45 | * \brief The function detected that the arguments violate the function 46 | * contract. 47 | */ 48 | CXError_InvalidArguments = 3, 49 | 50 | /** 51 | * \brief An AST deserialization error has occurred. 52 | */ 53 | CXError_ASTReadError = 4 54 | } 55 | -------------------------------------------------------------------------------- /tests/functional/clang-c/CXString.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides the interface to C Index strings. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.cx_string; 15 | 16 | extern (C): 17 | 18 | /** 19 | * \defgroup CINDEX_STRING String manipulation routines 20 | * \ingroup CINDEX 21 | * 22 | * @{ 23 | */ 24 | 25 | /** 26 | * \brief A character string. 27 | * 28 | * The \c CXString type is used to return strings from the interface when 29 | * the ownership of that string might differ from one call to the next. 30 | * Use \c clang_getCString() to retrieve the string data and, once finished 31 | * with the string data, call \c clang_disposeString() to free the string. 32 | */ 33 | struct CXString 34 | { 35 | const(void)* data; 36 | uint private_flags; 37 | } 38 | 39 | struct CXStringSet 40 | { 41 | CXString* Strings; 42 | uint Count; 43 | } 44 | 45 | /** 46 | * \brief Retrieve the character data associated with the given string. 47 | */ 48 | const(char)* clang_getCString (CXString string); 49 | 50 | /** 51 | * \brief Free the given string. 52 | */ 53 | void clang_disposeString (CXString string); 54 | 55 | /** 56 | * \brief Free the given string set. 57 | */ 58 | void clang_disposeStringSet (CXStringSet* set); 59 | 60 | /** 61 | * @} 62 | */ 63 | 64 | -------------------------------------------------------------------------------- /tests/functional/clang-c/CXErrorCode.h: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides the CXErrorCode enumerators. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | #ifndef LLVM_CLANG_C_CXERRORCODE_H 15 | #define LLVM_CLANG_C_CXERRORCODE_H 16 | 17 | #include "clang-c/Platform.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * \brief Error codes returned by libclang routines. 25 | * 26 | * Zero (\c CXError_Success) is the only error code indicating success. Other 27 | * error codes, including not yet assigned non-zero values, indicate errors. 28 | */ 29 | enum CXErrorCode { 30 | /** 31 | * \brief No error. 32 | */ 33 | CXError_Success = 0, 34 | 35 | /** 36 | * \brief A generic error code, no further details are available. 37 | * 38 | * Errors of this kind can get their own specific error codes in future 39 | * libclang versions. 40 | */ 41 | CXError_Failure = 1, 42 | 43 | /** 44 | * \brief libclang crashed while performing the requested operation. 45 | */ 46 | CXError_Crashed = 2, 47 | 48 | /** 49 | * \brief The function detected that the arguments violate the function 50 | * contract. 51 | */ 52 | CXError_InvalidArguments = 3, 53 | 54 | /** 55 | * \brief An AST deserialization error has occurred. 56 | */ 57 | CXError_ASTReadError = 4 58 | }; 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | #endif 64 | 65 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue8.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Aug 26, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | // Fix 8: Typedef and anonymous structs. 11 | 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | #include 16 | 17 | typedef struct rd_kafka { 18 | int dummy; 19 | } rd_kafka_t; 20 | 21 | typedef struct rd_kafka_topic { 22 | int dummy; 23 | } rd_kafka_topic_t; 24 | 25 | typedef struct rd_kafka_metadata { 26 | int broker_cnt; /* Number of brokers in 'brokers' */ 27 | struct rd_kafka_metadata_broker *brokers; /* Brokers */ 28 | 29 | int topic_cnt; /* Number of topics in 'topics' */ 30 | struct rd_kafka_metadata_topic *topics; /* Topics */ 31 | 32 | int32_t orig_broker_id; /* Broker originating this metadata */ 33 | char *orig_broker_name; /* Name of originating broker */ 34 | } rd_kafka_metadata_t; 35 | 36 | int rd_kafka_metadata (rd_kafka_t *rk, int all_topics, 37 | rd_kafka_topic_t *only_rkt, 38 | const struct rd_kafka_metadata **metadatap, 39 | int timeout_ms); 40 | C", 41 | q"D 42 | extern (C): 43 | 44 | struct rd_kafka 45 | { 46 | int dummy; 47 | } 48 | 49 | alias rd_kafka_t = rd_kafka; 50 | 51 | struct rd_kafka_topic 52 | { 53 | int dummy; 54 | } 55 | 56 | alias rd_kafka_topic_t = rd_kafka_topic; 57 | 58 | struct rd_kafka_metadata_ 59 | { 60 | int broker_cnt; /* Number of brokers in 'brokers' */ 61 | struct rd_kafka_metadata_broker; 62 | rd_kafka_metadata_broker* brokers; /* Brokers */ 63 | 64 | int topic_cnt; /* Number of topics in 'topics' */ 65 | struct rd_kafka_metadata_topic; 66 | rd_kafka_metadata_topic* topics; /* Topics */ 67 | 68 | int orig_broker_id; /* Broker originating this metadata */ 69 | char* orig_broker_name; /* Name of originating broker */ 70 | } 71 | 72 | alias rd_kafka_metadata_t = rd_kafka_metadata_; 73 | 74 | int rd_kafka_metadata ( 75 | rd_kafka_t* rk, 76 | int all_topics, 77 | rd_kafka_topic_t* only_rkt, 78 | const(rd_kafka_metadata_*)* metadatap, 79 | int timeout_ms); 80 | D"); 81 | 82 | } 83 | -------------------------------------------------------------------------------- /tests/functional/clang-c/CXString.h: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides the interface to C Index strings. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | #ifndef LLVM_CLANG_C_CXSTRING_H 15 | #define LLVM_CLANG_C_CXSTRING_H 16 | 17 | #include "clang-c/Platform.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * \defgroup CINDEX_STRING String manipulation routines 25 | * \ingroup CINDEX 26 | * 27 | * @{ 28 | */ 29 | 30 | /** 31 | * \brief A character string. 32 | * 33 | * The \c CXString type is used to return strings from the interface when 34 | * the ownership of that string might differ from one call to the next. 35 | * Use \c clang_getCString() to retrieve the string data and, once finished 36 | * with the string data, call \c clang_disposeString() to free the string. 37 | */ 38 | typedef struct { 39 | const void *data; 40 | unsigned private_flags; 41 | } CXString; 42 | 43 | typedef struct { 44 | CXString *Strings; 45 | unsigned Count; 46 | } CXStringSet; 47 | 48 | /** 49 | * \brief Retrieve the character data associated with the given string. 50 | */ 51 | CINDEX_LINKAGE const char *clang_getCString(CXString string); 52 | 53 | /** 54 | * \brief Free the given string. 55 | */ 56 | CINDEX_LINKAGE void clang_disposeString(CXString string); 57 | 58 | /** 59 | * \brief Free the given string set. 60 | */ 61 | CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set); 62 | 63 | /** 64 | * @} 65 | */ 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | #endif 71 | 72 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue46.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jun 27, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | import dstep.translator.Options; 11 | 12 | // Fix 46: Generating code that will not compile. 13 | version (Posix) 14 | { 15 | unittest 16 | { 17 | Options options; 18 | options.reduceAliases = true; 19 | 20 | assertTranslates( 21 | q"C 22 | 23 | typedef unsigned char __u8; 24 | typedef unsigned int __u32; 25 | typedef __signed__ long __s64; 26 | typedef unsigned long __u64; 27 | 28 | struct stats_t { 29 | __u8 scale; 30 | union { 31 | __u64 uvalue; 32 | __s64 svalue; 33 | }; 34 | } __attribute__ ((packed)); 35 | 36 | 37 | #define MAX_STATS 4 38 | 39 | struct fe_stats_t { 40 | __u8 len; 41 | struct stats_t stat[MAX_STATS]; 42 | } __attribute__ ((packed)); 43 | 44 | struct property_t { 45 | __u32 cmd; 46 | __u32 reserved[3]; 47 | union { 48 | __u32 data; 49 | struct fe_stats_t st; 50 | struct { 51 | __u8 data[32]; 52 | __u32 len; 53 | __u32 reserved1[3]; 54 | void *reserved2; 55 | } buffer; 56 | } u; 57 | int result; 58 | } __attribute__ ((packed)); 59 | C", q"D 60 | extern (C): 61 | 62 | struct stats_t 63 | { 64 | align (1): 65 | 66 | ubyte scale; 67 | 68 | union 69 | { 70 | ulong uvalue; 71 | long svalue; 72 | } 73 | } 74 | 75 | enum MAX_STATS = 4; 76 | 77 | struct fe_stats_t 78 | { 79 | align (1): 80 | 81 | ubyte len; 82 | stats_t[MAX_STATS] stat; 83 | } 84 | 85 | struct property_t 86 | { 87 | align (1): 88 | 89 | uint cmd; 90 | uint[3] reserved; 91 | 92 | union _Anonymous_0 93 | { 94 | uint data; 95 | fe_stats_t st; 96 | 97 | struct _Anonymous_1 98 | { 99 | ubyte[32] data; 100 | uint len; 101 | uint[3] reserved1; 102 | void* reserved2; 103 | } 104 | 105 | _Anonymous_1 buffer; 106 | } 107 | 108 | _Anonymous_0 u; 109 | int result; 110 | } 111 | D", options); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue141.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 23, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Options; 10 | 11 | // Fix 141: Use of _IO, _IOR, etc. 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | #define _IOC_NRSHIFT 0 16 | #define _IOC_TYPESHIFT 1 17 | #define _IOC_SIZESHIFT 2 18 | #define _IOC_DIRSHIFT 3 19 | 20 | #define _IOC_NONE 0U 21 | #define _IOC_READ 2U 22 | 23 | #define _IOC(dir,type,nr,size) \ 24 | (((dir) << _IOC_DIRSHIFT) | \ 25 | ((type) << _IOC_TYPESHIFT) | \ 26 | ((nr) << _IOC_NRSHIFT) | \ 27 | ((size) << _IOC_SIZESHIFT)) 28 | 29 | #define _IOC_TYPECHECK(t) (sizeof(t)) 30 | 31 | #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) 32 | #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) 33 | 34 | typedef struct { } foo_status_t; 35 | typedef unsigned int __u32; 36 | typedef unsigned short __u16; 37 | 38 | #define FE_READ_STATUS _IOR('o', 69, foo_status_t) 39 | #define FE_READ_BER _IOR('o', 70, __u32) 40 | #define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, __u16) 41 | #define FE_READ_SNR _IOR('o', 72, __u16) 42 | #define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32) 43 | C", 44 | q"D 45 | extern (C): 46 | 47 | enum _IOC_NRSHIFT = 0; 48 | enum _IOC_TYPESHIFT = 1; 49 | enum _IOC_SIZESHIFT = 2; 50 | enum _IOC_DIRSHIFT = 3; 51 | 52 | enum _IOC_NONE = 0U; 53 | enum _IOC_READ = 2U; 54 | 55 | extern (D) auto _IOC(T0, T1, T2, T3)(auto ref T0 dir, auto ref T1 type, auto ref T2 nr, auto ref T3 size) 56 | { 57 | return (dir << _IOC_DIRSHIFT) | (type << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT); 58 | } 59 | 60 | extern (D) size_t _IOC_TYPECHECK(t)() 61 | { 62 | return t.sizeof; 63 | } 64 | 65 | extern (D) auto _IO(T0, T1)(auto ref T0 type, auto ref T1 nr) 66 | { 67 | return _IOC(_IOC_NONE, type, nr, 0); 68 | } 69 | 70 | extern (D) auto _IOR(size, T0, T1)(auto ref T0 type, auto ref T1 nr) 71 | { 72 | return _IOC(_IOC_READ, type, nr, _IOC_TYPECHECK!size()); 73 | } 74 | 75 | struct foo_status_t 76 | { 77 | } 78 | 79 | enum FE_READ_STATUS = _IOR!foo_status_t('o', 69); 80 | enum FE_READ_BER = _IOR!uint('o', 70); 81 | enum FE_READ_SIGNAL_STRENGTH = _IOR!ushort('o', 71); 82 | enum FE_READ_SNR = _IOR!ushort('o', 72); 83 | enum FE_READ_UNCORRECTED_BLOCKS = _IOR!uint('o', 73); 84 | D"); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /tools/install_dc.ps1: -------------------------------------------------------------------------------- 1 | Set-StrictMode -Version Latest 2 | $ErrorActionPreference = 'Stop' 3 | $PSDefaultParameterValues['*:ErrorAction'] = 'Stop' 4 | 5 | function Get-LatestVersion($url) 6 | { 7 | (Invoke-WebRequest $url).toString().replace("`n","").replace("`r","") 8 | } 9 | 10 | function ResolveLatestDMD 11 | { 12 | $version = $env:DVersion 13 | 14 | if ($version -eq 'stable') 15 | { 16 | $version = Get-LatestVersion('http://downloads.dlang.org/releases/LATEST') 17 | $url = "http://downloads.dlang.org/releases/2.x/$version/dmd.$version.windows.7z" 18 | } 19 | elseif ($version -eq 'beta') 20 | { 21 | $version = Get-LatestVersion('http://downloads.dlang.org/pre-releases/LATEST') 22 | $latestVersion = $latest.split("-")[0].split("~")[0] 23 | $url = "http://downloads.dlang.org/pre-releases/2.x/$latestVersion/dmd.$version.windows.7z" 24 | } 25 | elseif ($version -eq 'nightly') 26 | { 27 | $url = 'http://nightlies.dlang.org/dmd-master-2017-05-20/dmd.master.windows.7z' 28 | } 29 | else 30 | { 31 | $url = "http://downloads.dlang.org/releases/2.x/$version/dmd.$version.windows.7z" 32 | } 33 | 34 | $bin_path = "/dmd2/windows/bin" 35 | $env:PATH += ";$bin_path" 36 | 37 | $url, $bin_path 38 | } 39 | 40 | function Get-LatestLDCVersion($latest) 41 | { 42 | Get-LatestVersion("https://ldc-developers.github.io/$latest") 43 | } 44 | 45 | function ResolveLatestLDC 46 | { 47 | $version = $env:DVersion 48 | 49 | if ($version -eq 'stable') 50 | { 51 | $version = Get-LatestLDCVersion('LATEST') 52 | } 53 | elseif ($version -eq 'beta') 54 | { 55 | $version = Get-LatestLDCVersion('LATEST_BETA') 56 | } 57 | 58 | $bin_path = "/ldc2-$version-windows-$env:PLATFORM/bin" 59 | $url = 'https://github.com/ldc-developers/ldc/releases/download/' ` 60 | + "v$version/ldc2-$version-windows-$env:PLATFORM.7z" 61 | 62 | $env:PATH += ";$bin_path" 63 | 64 | $url, $bin_path 65 | } 66 | 67 | function SetUpDCompiler 68 | { 69 | if ($env:d -eq 'dmd') 70 | { 71 | $url, $bin_path = ResolveLatestDMD 72 | $env:DC = 'dmd' 73 | } 74 | elseif ($env:d -eq 'ldc') 75 | { 76 | $url, $bin_path = ResolveLatestLDC 77 | $env:DC = 'ldc2' 78 | } 79 | else 80 | { 81 | echo "Unrecognized compiler $env:d" 82 | $host.SetShouldExit(-1) 83 | return 84 | } 85 | 86 | echo "Downloading ..." 87 | echo "$url" 88 | Invoke-WebRequest "$url" -OutFile /dc.7z 89 | echo 'Finished' 90 | 7z x /dc.7z -o/ > $null 91 | cp "$bin_path/libcurl.dll" . 92 | } 93 | 94 | SetUpDCompiler 95 | -------------------------------------------------------------------------------- /dstep/translator/TypedefIndex.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: May 26, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.translator.TypedefIndex; 8 | 9 | import clang.c.Index; 10 | import clang.Cursor; 11 | import clang.TranslationUnit; 12 | 13 | 14 | class TypedefIndex 15 | { 16 | import std.typecons: Flag, No; 17 | 18 | private Cursor[Cursor] typedefs; 19 | 20 | this(TranslationUnit translUnit) 21 | { 22 | this(translUnit, (ref const(Cursor)) => false); 23 | } 24 | 25 | this(TranslationUnit translUnit, bool function(ref const(Cursor)) isWantedCursor) 26 | { 27 | import std.functional: toDelegate; 28 | this(translUnit, isWantedCursor.toDelegate); 29 | } 30 | 31 | this(TranslationUnit translUnit, bool delegate(ref const(Cursor)) isWantedCursor) 32 | { 33 | bool[Cursor] visited; 34 | 35 | auto file = translUnit.file; 36 | 37 | foreach (cursor; translUnit.cursor.all) 38 | { 39 | if (cursor.file == file || (isWantedCursor !is null && isWantedCursor(cursor))) 40 | { 41 | visited[cursor] = true; 42 | inspect(cursor, visited); 43 | } 44 | } 45 | } 46 | 47 | private void inspect(Cursor cursor, bool[Cursor] visited) 48 | { 49 | if (cursor.kind == CXCursorKind.typedefDecl) 50 | { 51 | foreach (child; cursor.all) 52 | { 53 | if (child.kind == CXCursorKind.typeRef 54 | || child.isDeclaration) 55 | { 56 | if (child.referenced !in typedefs) 57 | { 58 | typedefs[child.referenced] = cursor; 59 | typedefs[child.referenced.canonical] = cursor; 60 | } 61 | } 62 | } 63 | } 64 | else if ((cursor in visited) is null) 65 | { 66 | foreach (child; cursor.all) 67 | { 68 | visited[cursor] = true; 69 | inspect(cursor, visited); 70 | } 71 | } 72 | } 73 | 74 | Cursor typedefParent(in Cursor cursor) 75 | { 76 | auto result = cursor in typedefs; 77 | 78 | if (result is null) 79 | return cursor.empty; 80 | else 81 | return *result; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/unit/TranslateEnumValuesUnitTests.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: October 19, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import std.stdio; 8 | import Common; 9 | import dstep.translator.Translator; 10 | 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | typedef enum 15 | { 16 | a = 1, 17 | b = 2, 18 | } Foo; 19 | 20 | typedef enum 21 | { 22 | c = b, 23 | d = c | a 24 | } Bar; 25 | C", 26 | q"D 27 | extern (C): 28 | 29 | enum Foo 30 | { 31 | a = 1, 32 | b = 2 33 | } 34 | 35 | enum Bar 36 | { 37 | c = Foo.b, 38 | d = c | Foo.a 39 | } 40 | D"); 41 | 42 | } 43 | 44 | unittest 45 | { 46 | assertTranslates(q"C 47 | enum Qux 48 | { 49 | FOO = 1 << 0, 50 | BAR = 1 << 1, 51 | BAZ = 1 << 2 52 | }; 53 | C", 54 | q"D 55 | extern (C): 56 | 57 | enum Qux 58 | { 59 | FOO = 1 << 0, 60 | BAR = 1 << 1, 61 | BAZ = 1 << 2 62 | } 63 | D"); 64 | 65 | } 66 | 67 | unittest 68 | { 69 | assertTranslates(q"C 70 | enum Foo 71 | { 72 | a = 0x1, 73 | b = 0x2, 74 | c = 1 << 0, 75 | d = ((1 << 22) - 1) 76 | }; 77 | C", 78 | q"D 79 | extern (C): 80 | 81 | enum Foo 82 | { 83 | a = 0x1, 84 | b = 0x2, 85 | c = 1 << 0, 86 | d = (1 << 22) - 1 87 | } 88 | D"); 89 | 90 | } 91 | 92 | unittest 93 | { 94 | assertTranslates(q"C 95 | enum Foo 96 | { 97 | a = 1, 98 | b = 2, 99 | c = b, 100 | d = c | a 101 | }; 102 | C", 103 | q"D 104 | extern (C): 105 | 106 | enum Foo 107 | { 108 | a = 1, 109 | b = 2, 110 | c = b, 111 | d = c | a 112 | } 113 | D"); 114 | 115 | } 116 | 117 | unittest 118 | { 119 | assertTranslates(q"C 120 | enum Foo 121 | { 122 | a = 1, 123 | b = 2, 124 | }; 125 | 126 | enum Bar 127 | { 128 | c = b, 129 | d = c | a 130 | }; 131 | C", 132 | q"D 133 | extern (C): 134 | 135 | enum Foo 136 | { 137 | a = 1, 138 | b = 2 139 | } 140 | 141 | enum Bar 142 | { 143 | c = Foo.b, 144 | d = c | Foo.a 145 | } 146 | D"); 147 | 148 | } 149 | 150 | unittest 151 | { 152 | Options options; 153 | options.renameEnumMembers = true; 154 | 155 | assertTranslates(q"C 156 | enum Foo 157 | { 158 | AAA = 1, 159 | BBB = 2, 160 | }; 161 | 162 | enum Bar 163 | { 164 | CCC = BBB, 165 | DDD = CCC | AAA 166 | }; 167 | C", 168 | q"D 169 | extern (C): 170 | 171 | enum Foo 172 | { 173 | aaa = 1, 174 | bbb = 2 175 | } 176 | 177 | enum Bar 178 | { 179 | ccc = Foo.bbb, 180 | ddd = ccc | Foo.aaa 181 | } 182 | D", options); 183 | 184 | } 185 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue137.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jan 26, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | import dstep.translator.Options; 10 | 11 | // Fix 116: struct member expansion 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | 16 | // FILE object wrapper for vfs access 17 | typedef struct { 18 | struct DB_vfs_s *vfs; 19 | } DB_FILE; 20 | 21 | typedef int DB_playItem_t; 22 | 23 | typedef struct DB_plugin_action_s { 24 | const char *title; 25 | const char *name; 26 | unsigned flags; 27 | // only use it if the code must be compatible with API 1.4 28 | // otherwise switch to callback2 29 | } DB_plugin_action_t; 30 | 31 | // vfs plugin 32 | // provides means for reading, seeking, etc 33 | // api is based on stdio 34 | typedef struct DB_vfs_s { 35 | // capabilities 36 | const char **(*get_schemes) (void); 37 | 38 | int (*is_streaming) (void); // return 1 if the plugin streaming data 39 | 40 | // this allows interruption of hanging network streams 41 | void (*abort) (DB_FILE *stream); 42 | 43 | // should return mime-type of a stream, if known; can be NULL 44 | const char * (*get_content_type) (DB_FILE *stream); 45 | 46 | // associates stream with a track, to allow dynamic metadata updating, like 47 | // in icy protocol 48 | void (*set_track) (DB_FILE *f, DB_playItem_t *it); 49 | } DB_vfs_t; 50 | C", 51 | q"D 52 | extern (C): 53 | 54 | // FILE object wrapper for vfs access 55 | struct DB_FILE 56 | { 57 | DB_vfs_s* vfs; 58 | } 59 | 60 | alias DB_playItem_t = int; 61 | 62 | struct DB_plugin_action_s 63 | { 64 | const(char)* title; 65 | const(char)* name; 66 | uint flags; 67 | // only use it if the code must be compatible with API 1.4 68 | // otherwise switch to callback2 69 | } 70 | 71 | alias DB_plugin_action_t = DB_plugin_action_s; 72 | 73 | // vfs plugin 74 | // provides means for reading, seeking, etc 75 | // api is based on stdio 76 | struct DB_vfs_s 77 | { 78 | // capabilities 79 | const(char*)* function () get_schemes; 80 | 81 | int function () is_streaming; // return 1 if the plugin streaming data 82 | 83 | // this allows interruption of hanging network streams 84 | void function (DB_FILE* stream) abort; 85 | 86 | // should return mime-type of a stream, if known; can be NULL 87 | const(char)* function (DB_FILE* stream) get_content_type; 88 | 89 | // associates stream with a track, to allow dynamic metadata updating, like 90 | // in icy protocol 91 | void function (DB_FILE* f, DB_playItem_t* it) set_track; 92 | } 93 | 94 | alias DB_vfs_t = DB_vfs_s; 95 | D"); 96 | 97 | } 98 | -------------------------------------------------------------------------------- /tests/functional/clang-c/LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | LLVM Release License 3 | ============================================================================== 4 | University of Illinois/NCSA 5 | Open Source License 6 | 7 | Copyright (c) 2007-2015 University of Illinois at Urbana-Champaign. 8 | All rights reserved. 9 | 10 | Developed by: 11 | 12 | LLVM Team 13 | 14 | University of Illinois at Urbana-Champaign 15 | 16 | http://llvm.org 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy of 19 | this software and associated documentation files (the "Software"), to deal with 20 | the Software without restriction, including without limitation the rights to 21 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 22 | of the Software, and to permit persons to whom the Software is furnished to do 23 | so, subject to the following conditions: 24 | 25 | * Redistributions of source code must retain the above copyright notice, 26 | this list of conditions and the following disclaimers. 27 | 28 | * Redistributions in binary form must reproduce the above copyright notice, 29 | this list of conditions and the following disclaimers in the 30 | documentation and/or other materials provided with the distribution. 31 | 32 | * Neither the names of the LLVM Team, University of Illinois at 33 | Urbana-Champaign, nor the names of its contributors may be used to 34 | endorse or promote products derived from this Software without specific 35 | prior written permission. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 39 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 43 | SOFTWARE. 44 | 45 | ============================================================================== 46 | The LLVM software contains code written by third parties. Such software will 47 | have its own individual LICENSE.TXT file in the directory in which it appears. 48 | This file will describe the copyrights, license, and restrictions which apply 49 | to that code. 50 | 51 | The disclaimer of warranty in the University of Illinois Open Source License 52 | applies to all code in the LLVM Distribution, and nothing in any of the 53 | other licenses gives permission to use the names of the LLVM Team or the 54 | University of Illinois to endorse or promote products derived from this 55 | Software. 56 | 57 | The following pieces of software have additional or alternate copyrights, 58 | licenses, and/or restrictions: 59 | 60 | Program Directory 61 | ------- --------- 62 | 63 | 64 | -------------------------------------------------------------------------------- /dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dstep", 3 | "description": "A tool for translating C and Objective-C headers to D modules", 4 | "authors": ["Jacob Carlborg"], 5 | "homepage": "https://github.com/jacob-carlborg/dstep", 6 | "license": "BSL-1.0", 7 | "copyright": "Copyright (c) 2011-2016 Jacob Carlborg. All rights reserved.", 8 | 9 | "targetType": "executable", 10 | "targetPath": "bin", 11 | 12 | "buildRequirements": ["silenceWarnings"], 13 | "stringImportPaths": ["resources"], 14 | 15 | "preGenerateCommands-posix": ["$DUB $PACKAGE_DIR/tools/generate_version.d"], 16 | "preGenerateCommands-windows": ["$DUB $PACKAGE_DIR\\tools\\/generate_version.d"], 17 | 18 | "preBuildCommands": [ 19 | "$DUB configure --if-needed" 20 | ], 21 | 22 | "lflags": ["@$PACKAGE_DIR/linker_flags.txt"], 23 | "libs-windows": ["version"], 24 | 25 | "buildTypes": { 26 | "release": { 27 | "buildOptions": ["optimize", "inline"], 28 | "dflags-osx-ldc": ["-flto=full"], 29 | "lflags-osx-ldc": ["-dead_strip"] 30 | } 31 | }, 32 | 33 | "configurations": [ 34 | { 35 | "name": "default", 36 | "targetName": "dstep", 37 | "mainSourceFile": "dstep/main.d", 38 | "sourcePaths": ["dstep", "clang"], 39 | "importPaths": ["."] 40 | }, 41 | 42 | { 43 | "name": "test-functional", 44 | "targetName": "functional", 45 | "targetType": "executable", 46 | "targetPath": "bin/test", 47 | "sourcePaths": ["tests/support"], 48 | "sourceFiles": ["tests/functional/Tests.d", "dstep/driver/Util.d"], 49 | "buildOptions": ["unittests", "debugMode", "debugInfo"], 50 | "dflags": ["-main"], 51 | 52 | "libs-windows": ["ole32"] 53 | }, 54 | 55 | { 56 | "name": "test-unit", 57 | "targetName": "unit", 58 | "targetType": "executable", 59 | "targetPath": "bin/test", 60 | "sourcePaths": ["dstep", "clang", "tests/unit", "tests/support"], 61 | "excludedSourceFiles": ["dstep/main.d"], 62 | "dflags": ["-main"], 63 | "buildOptions" : ["unittests", "debugMode", "debugInfo"] 64 | }, 65 | 66 | { 67 | "name": "test-library", 68 | "targetName": "library", 69 | "targetType": "executable", 70 | "targetPath": "bin/test", 71 | "mainSourceFile": "library_test.d" 72 | }, 73 | 74 | { 75 | "name": "unittest", 76 | "targetName": "wrapper", 77 | "targetPath": "bin/test", 78 | "mainSourceFile": "test.d" 79 | }, 80 | 81 | { 82 | "name": "library", 83 | "targetType": "library", 84 | "sourcePaths": ["dstep", "clang"], 85 | "importPaths": ["."], 86 | "excludedSourceFiles": ["dstep/main.d"] 87 | } 88 | ] 89 | } 90 | -------------------------------------------------------------------------------- /clang/SourceLocation.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Jan 29, 2012 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.SourceLocation; 8 | 9 | import clang.c.Index; 10 | import clang.File; 11 | import clang.Util; 12 | 13 | struct SourceLocation 14 | { 15 | mixin CX; 16 | 17 | struct Spelling 18 | { 19 | File file; 20 | uint line; 21 | uint column; 22 | uint offset; 23 | } 24 | 25 | @property static SourceLocation empty() 26 | { 27 | return SourceLocation(clang_getNullLocation()); 28 | } 29 | 30 | @property Spelling spelling() const 31 | { 32 | Spelling spell; 33 | 34 | clang_getSpellingLocation( 35 | cx, 36 | &spell.file.cx, 37 | &spell.line, 38 | &spell.column, 39 | &spell.offset); 40 | 41 | return spell; 42 | } 43 | 44 | @property Spelling expansion() const 45 | { 46 | Spelling spell; 47 | 48 | clang_getExpansionLocation( 49 | cx, 50 | &spell.file.cx, 51 | &spell.line, 52 | &spell.column, 53 | &spell.offset); 54 | 55 | return spell; 56 | } 57 | 58 | @property string path() const 59 | { 60 | return file.name; 61 | } 62 | 63 | @property File file() const 64 | { 65 | File file; 66 | clang_getExpansionLocation(cx, &file.cx, null, null, null); 67 | return file; 68 | } 69 | 70 | @property uint line() const 71 | { 72 | uint result; 73 | clang_getExpansionLocation(cx, null, &result, null, null); 74 | return result; 75 | } 76 | 77 | @property uint column() const 78 | { 79 | uint result; 80 | clang_getExpansionLocation(cx, null, null, &result, null); 81 | return result; 82 | } 83 | 84 | @property uint offset() const 85 | { 86 | uint result; 87 | clang_getExpansionLocation(cx, null, null, null, &result); 88 | return result; 89 | } 90 | 91 | @property bool isFromMainFile() const 92 | { 93 | return clang_Location_isFromMainFile(cx) != 0; 94 | } 95 | 96 | @property string toString() const 97 | { 98 | import std.format : format; 99 | auto localSpelling = spelling; 100 | 101 | return format( 102 | "SourceLocation(file = %s, line = %d, column = %d, offset = %d)", 103 | localSpelling.file, 104 | localSpelling.line, 105 | localSpelling.column, 106 | localSpelling.offset); 107 | } 108 | 109 | @property string toColonSeparatedString() const 110 | { 111 | import std.format : format; 112 | auto localSpelling = spelling; 113 | 114 | return format( 115 | "%s:%d:%d", 116 | localSpelling.file.name, 117 | localSpelling.line, 118 | localSpelling.column); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/unit/IncludeGraphTests.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 18, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import Common; 8 | 9 | import clang.c.Index; 10 | import clang.Compiler; 11 | import clang.Index; 12 | import clang.TranslationUnit; 13 | import clang.Util; 14 | 15 | import dstep.translator.HeaderIndex; 16 | 17 | static TranslationUnit makeTranslationUnit( 18 | string sourceFilename, 19 | const string[] commandLineArgs = ["-Wno-missing-declarations"], 20 | uint options = CXTranslationUnit_Flags.detailedPreprocessingRecord) 21 | { 22 | import std.algorithm; 23 | import std.array; 24 | 25 | Compiler compiler; 26 | 27 | auto index = Index(false, false); 28 | 29 | return TranslationUnit.parse( 30 | index, 31 | sourceFilename, 32 | commandLineArgs ~ compiler.internalFlags, 33 | compiler.internalHeaders, 34 | options); 35 | } 36 | 37 | static IncludeGraph makeIncludeGraph(string sourceFilename) 38 | { 39 | return new IncludeGraph(makeTranslationUnit(sourceFilename)); 40 | } 41 | 42 | unittest 43 | { 44 | const string file = "tests/functional/graph/file.h".asAbsNormPath(); 45 | const string subfile1 = "tests/functional/graph/subfile1.h".asAbsNormPath(); 46 | const string subfile2 = "tests/functional/graph/subfile2.h".asAbsNormPath(); 47 | const string subfile3 = "tests/functional/graph/subfile3.h".asAbsNormPath(); 48 | const string subsubfile1 = "tests/functional/graph/subsubfile1.h".asAbsNormPath(); 49 | const string subsubfile2 = "tests/functional/graph/subsubfile2.h".asAbsNormPath(); 50 | const string subsubfile3 = "tests/functional/graph/subsubfile3.h".asAbsNormPath(); 51 | 52 | auto includeGraph = makeIncludeGraph(file); 53 | 54 | // The file is reachable by itself. 55 | assert(includeGraph.isReachableBy(file, file)); 56 | assert(includeGraph.isReachableBy(subfile3, subfile3)); 57 | 58 | // The file is reachable by its direct includer. 59 | assert(includeGraph.isReachableBy(subfile2, file)); 60 | 61 | // The file is reachable by its indirect includer. 62 | assert(includeGraph.isReachableBy(subsubfile3, file)); 63 | 64 | // The file isn't reachable by unrelated file. 65 | assert(!includeGraph.isReachableBy(subsubfile3, subfile1)); 66 | 67 | // The inclusion cannot be reversed. 68 | assert(!includeGraph.isReachableBy(file, subsubfile3)); 69 | } 70 | 71 | unittest 72 | { 73 | import std.algorithm; 74 | 75 | auto translationUnit = makeTranslationUnit( 76 | "tests/functional/clang-c/Index.h", 77 | ["-Wno-missing-declarations", "-Itests/functional"]); 78 | auto headerIndex = new HeaderIndex(translationUnit); 79 | 80 | auto timeT = translationUnit.cursor.children.filter!(x => x.spelling == "time_t").front; 81 | 82 | assert(headerIndex.searchKnownModules(timeT) == "core.stdc.time"); 83 | } 84 | 85 | unittest 86 | { 87 | auto translationUnit = makeTranslationUnit( 88 | "tests/functional/graph/self_including_main.h", 89 | ["-Wno-missing-declarations", "-Itests/functional"]); 90 | 91 | new HeaderIndex(translationUnit); 92 | } 93 | -------------------------------------------------------------------------------- /test.d: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | import std.array; 4 | import std.process; 5 | import std.stdio; 6 | import std.file; 7 | import std.path; 8 | import std.algorithm; 9 | import std.string; 10 | import std.traits : ReturnType; 11 | 12 | void main () 13 | { 14 | TestRunner().run(); 15 | } 16 | 17 | private: 18 | 19 | /** 20 | * The available test groups. 21 | * 22 | * The tests will be run in the order specified here. 23 | */ 24 | enum TestGroup 25 | { 26 | unit = "unit", 27 | library = "library", 28 | functional = "functional" 29 | } 30 | 31 | struct TestRunner 32 | { 33 | void run () 34 | { 35 | import std.traits : EnumMembers; 36 | 37 | foreach (test ; EnumMembers!TestGroup) 38 | runTest!(test); 39 | 40 | stdout.flush(); 41 | } 42 | 43 | /** 44 | * Run a single group of tests, i.e. functional, library or unit test. 45 | * 46 | * Params: 47 | * testGroup = the test group to run 48 | * 49 | * Returns: the exist code of the test run 50 | */ 51 | void runTest (TestGroup testGroup)() 52 | { 53 | import std.string : capitalize; 54 | 55 | enum beforeFunction = "before" ~ testGroup.capitalize; 56 | 57 | static if (is(typeof(mixin(beforeFunction)))) 58 | mixin(beforeFunction ~ "();"); 59 | 60 | writef("Running %s tests ", testGroup); 61 | stdout.flush(); 62 | const command = dubShellCommand("--config=test-" ~ testGroup); 63 | executeCommand(command); 64 | } 65 | 66 | void beforeFunctional() @safe 67 | { 68 | if (dstepBuilt) 69 | return; 70 | 71 | writeln("Building DStep"); 72 | const command = dubShellCommand("build", "--build=debug"); 73 | executeCommand(command); 74 | } 75 | } 76 | 77 | @safe: 78 | 79 | bool dstepBuilt() 80 | { 81 | import std.file : exists; 82 | 83 | version (Windows) 84 | enum dstepPath = "bin/dstep.exe"; 85 | else version (Posix) 86 | enum dstepPath = "bin/dstep"; 87 | 88 | return exists(dstepPath); 89 | } 90 | 91 | void executeCommand(const string[] args ...) 92 | { 93 | import std.process : spawnProcess, wait; 94 | import std.array : join; 95 | 96 | if (spawnProcess(args).wait() != 0) 97 | throw new Exception("Failed to execute command: " ~ args.join(' ')); 98 | } 99 | 100 | string[] dubShellCommand(string[] subCommands ...) 101 | { 102 | return (["dub", "--verror"] ~ subCommands ~ dubArch) 103 | .filter!(e => e.length > 0) 104 | .array; 105 | } 106 | 107 | string defaultArchitecture() 108 | { 109 | version (X86_64) 110 | return "x86_64"; 111 | else 112 | { 113 | version (DigitalMars) 114 | return "x86_mscoff"; 115 | else 116 | return "x86"; 117 | } 118 | } 119 | 120 | string dubArch() 121 | { 122 | version (Windows) 123 | { 124 | import std.process : environment; 125 | import std.string : split; 126 | 127 | const architecture = environment 128 | .get("DUB_ARCH", defaultArchitecture) 129 | .split(" ")[$ - 1]; 130 | 131 | return "--arch=" ~ architecture; 132 | 133 | } 134 | else 135 | return ""; 136 | } 137 | -------------------------------------------------------------------------------- /clang/Compiler.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2015 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Jan 31, 2015 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.Compiler; 8 | 9 | import std.path; 10 | import std.typetuple : staticMap; 11 | 12 | import clang.c.Index; 13 | 14 | struct Compiler 15 | { 16 | private 17 | { 18 | version (Windows) 19 | enum root = `C:\`; 20 | 21 | else 22 | enum root = "/"; 23 | 24 | string virtualPath_; 25 | string[] sysRootFlag_; 26 | 27 | static template toInternalHeader (string file) 28 | { 29 | enum toInternalHeader = InternalHeader(file, import(file)); 30 | } 31 | 32 | static struct InternalHeader 33 | { 34 | string filename; 35 | string content; 36 | } 37 | 38 | enum internalHeaders_ = [ 39 | staticMap!( 40 | toInternalHeader, 41 | "__stddef_max_align_t.h", 42 | "float.h", 43 | "limits.h", 44 | "stdarg.h", 45 | "stdbool.h", 46 | "stddef.h" 47 | ) 48 | ]; 49 | } 50 | 51 | string[] internalFlags () 52 | { 53 | import std.algorithm : map; 54 | import std.array : array; 55 | import std.range : chain; 56 | 57 | return extraIncludePaths 58 | .map!(path => "-I" ~ path) 59 | .chain(sysRootFlag) 60 | .array; 61 | } 62 | 63 | CXUnsavedFile[] internalHeaders () 64 | { 65 | import std.algorithm : map; 66 | import std.array : array; 67 | import std.string : toStringz; 68 | 69 | return internalHeaders_.map!((e) { 70 | auto path = buildPath(virtualPath, e.filename); 71 | return CXUnsavedFile(path.toStringz, e.content.ptr, cast(uint)e.content.length); 72 | }).array(); 73 | } 74 | 75 | private: 76 | 77 | string[] extraIncludePaths () 78 | { 79 | return [virtualPath]; 80 | } 81 | 82 | string virtualPath () 83 | { 84 | import std.random; 85 | import std.conv; 86 | 87 | if (virtualPath_.length) 88 | return virtualPath_; 89 | 90 | return virtualPath_ = buildPath(root, uniform(1, 10_000_000).to!string); 91 | } 92 | 93 | string[] sysRootFlag () 94 | { 95 | if (sysRootFlag_.length) 96 | return sysRootFlag_; 97 | 98 | version (OSX) 99 | { 100 | import std.string : strip; 101 | import std.array : join; 102 | import std.format : format; 103 | import std.process : execute; 104 | 105 | import dstep.core.Exceptions : DStepException; 106 | 107 | static immutable command = ["xcrun", "--show-sdk-path", "--sdk", "macosx"]; 108 | const result = execute(command); 109 | 110 | if (result.status == 0) 111 | return sysRootFlag_ = ["-isysroot", result.output.strip]; 112 | 113 | enum fmt = "Failed get the path of the SDK.\nThe command '%s' " ~ 114 | "returned the following output:\n%s"; 115 | 116 | const message = format!fmt(command.join(" "), result.output); 117 | throw new DStepException(message); 118 | } 119 | 120 | else 121 | return null; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /clang/Diagnostic.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Oct 6, 2011 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module clang.Diagnostic; 8 | 9 | import std.typecons : RefCounted; 10 | 11 | import clang.c.Index; 12 | import clang.Util; 13 | 14 | struct Diagnostic 15 | { 16 | mixin CX; 17 | 18 | string format (uint options = clang_defaultDiagnosticDisplayOptions) 19 | { 20 | return toD(clang_formatDiagnostic(cx, options)); 21 | } 22 | 23 | @property CXDiagnosticSeverity severity () 24 | { 25 | return clang_getDiagnosticSeverity(cx); 26 | } 27 | 28 | @property toString() 29 | { 30 | return format; 31 | } 32 | } 33 | 34 | struct DiagnosticSet 35 | { 36 | private struct Container 37 | { 38 | CXDiagnosticSet set; 39 | 40 | ~this() 41 | { 42 | if (set != null) 43 | { 44 | clang_disposeDiagnosticSet(set); 45 | } 46 | } 47 | } 48 | 49 | private RefCounted!Container container; 50 | private size_t begin; 51 | private size_t end; 52 | 53 | private static RefCounted!Container makeContainer( 54 | CXDiagnosticSet set) 55 | { 56 | RefCounted!Container result; 57 | result.set = set; 58 | return result; 59 | } 60 | 61 | private this( 62 | RefCounted!Container container, 63 | size_t begin, 64 | size_t end) 65 | { 66 | this.container = container; 67 | this.begin = begin; 68 | this.end = end; 69 | } 70 | 71 | this(CXDiagnosticSet set) 72 | { 73 | container = makeContainer(set); 74 | begin = 0; 75 | end = clang_getNumDiagnosticsInSet(container.set); 76 | } 77 | 78 | @property bool empty() const 79 | { 80 | return begin >= end; 81 | } 82 | 83 | @property Diagnostic front() 84 | { 85 | return Diagnostic(clang_getDiagnosticInSet(container.set, cast(uint) begin)); 86 | } 87 | 88 | @property Diagnostic back() 89 | { 90 | return Diagnostic(clang_getDiagnosticInSet(container.set, cast(uint) (end - 1))); 91 | } 92 | 93 | @property void popFront() 94 | { 95 | ++begin; 96 | } 97 | 98 | @property void popBack() 99 | { 100 | --end; 101 | } 102 | 103 | @property DiagnosticSet save() 104 | { 105 | return this; 106 | } 107 | 108 | @property size_t length() const 109 | { 110 | return end - begin; 111 | } 112 | 113 | Diagnostic opIndex(size_t index) 114 | { 115 | return Diagnostic(clang_getDiagnosticInSet(container.set, cast(uint) (begin + index))); 116 | } 117 | 118 | DiagnosticSet opSlice(size_t begin, size_t end) 119 | { 120 | return DiagnosticSet(container, this.begin + begin, this.begin + end); 121 | } 122 | 123 | size_t opDollar() const 124 | { 125 | return length; 126 | } 127 | } 128 | 129 | CXDiagnosticSeverity severity(DiagnosticSet diagnostics) 130 | { 131 | import std.algorithm.searching : minPos; 132 | import std.algorithm.iteration : map; 133 | 134 | alias less = (a, b) => cast(uint) a > cast(uint) b; 135 | 136 | if (diagnostics.empty) 137 | return CXDiagnosticSeverity.ignored; 138 | else 139 | return diagnostics.map!(diagnostic => diagnostic.severity).minPos!less.front; 140 | } 141 | 142 | bool hasError(DiagnosticSet diagnostics) 143 | { 144 | auto severity = diagnostics.severity; 145 | 146 | return severity == CXDiagnosticSeverity.error || 147 | severity == CXDiagnosticSeverity.fatal; 148 | } 149 | -------------------------------------------------------------------------------- /resources/limits.h: -------------------------------------------------------------------------------- 1 | /*===---- limits.h - Standard header for integer sizes --------------------===*\ 2 | * 3 | * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | * See https://llvm.org/LICENSE.txt for license information. 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | * 7 | \*===----------------------------------------------------------------------===*/ 8 | 9 | #ifndef __CLANG_LIMITS_H 10 | #define __CLANG_LIMITS_H 11 | 12 | /* The system's limits.h may, in turn, try to #include_next GCC's limits.h. 13 | Avert this #include_next madness. */ 14 | #if defined __GNUC__ && !defined _GCC_LIMITS_H_ 15 | #define _GCC_LIMITS_H_ 16 | #endif 17 | 18 | /* System headers include a number of constants from POSIX in . 19 | Include it if we're hosted. */ 20 | #if __STDC_HOSTED__ && __has_include_next() 21 | #include_next 22 | #endif 23 | 24 | /* Many system headers try to "help us out" by defining these. No really, we 25 | know how big each datatype is. */ 26 | #undef SCHAR_MIN 27 | #undef SCHAR_MAX 28 | #undef UCHAR_MAX 29 | #undef SHRT_MIN 30 | #undef SHRT_MAX 31 | #undef USHRT_MAX 32 | #undef INT_MIN 33 | #undef INT_MAX 34 | #undef UINT_MAX 35 | #undef LONG_MIN 36 | #undef LONG_MAX 37 | #undef ULONG_MAX 38 | 39 | #undef CHAR_BIT 40 | #undef CHAR_MIN 41 | #undef CHAR_MAX 42 | 43 | /* C90/99 5.2.4.2.1 */ 44 | #define SCHAR_MAX __SCHAR_MAX__ 45 | #define SHRT_MAX __SHRT_MAX__ 46 | #define INT_MAX __INT_MAX__ 47 | #define LONG_MAX __LONG_MAX__ 48 | 49 | #define SCHAR_MIN (-__SCHAR_MAX__-1) 50 | #define SHRT_MIN (-__SHRT_MAX__ -1) 51 | #define INT_MIN (-__INT_MAX__ -1) 52 | #define LONG_MIN (-__LONG_MAX__ -1L) 53 | 54 | #define UCHAR_MAX (__SCHAR_MAX__*2 +1) 55 | #define USHRT_MAX (__SHRT_MAX__ *2 +1) 56 | #define UINT_MAX (__INT_MAX__ *2U +1U) 57 | #define ULONG_MAX (__LONG_MAX__ *2UL+1UL) 58 | 59 | #ifndef MB_LEN_MAX 60 | #define MB_LEN_MAX 1 61 | #endif 62 | 63 | #define CHAR_BIT __CHAR_BIT__ 64 | 65 | /* C2x 5.2.4.2.1 */ 66 | /* FIXME: This is using the placeholder dates Clang produces for these macros 67 | in C2x mode; switch to the correct values once they've been published. */ 68 | #if __STDC_VERSION__ >= 202000L 69 | #define BOOL_WIDTH __BOOL_WIDTH__ 70 | #define CHAR_WIDTH CHAR_BIT 71 | #define SCHAR_WIDTH CHAR_BIT 72 | #define UCHAR_WIDTH CHAR_BIT 73 | #define USHRT_WIDTH __SHRT_WIDTH__ 74 | #define SHRT_WIDTH __SHRT_WIDTH__ 75 | #define UINT_WIDTH __INT_WIDTH__ 76 | #define INT_WIDTH __INT_WIDTH__ 77 | #define ULONG_WIDTH __LONG_WIDTH__ 78 | #define LONG_WIDTH __LONG_WIDTH__ 79 | #define ULLONG_WIDTH __LLONG_WIDTH__ 80 | #define LLONG_WIDTH __LLONG_WIDTH__ 81 | 82 | #define BITINT_MAXWIDTH __BITINT_MAXWIDTH__ 83 | #endif 84 | 85 | #ifdef __CHAR_UNSIGNED__ /* -funsigned-char */ 86 | #define CHAR_MIN 0 87 | #define CHAR_MAX UCHAR_MAX 88 | #else 89 | #define CHAR_MIN SCHAR_MIN 90 | #define CHAR_MAX __SCHAR_MAX__ 91 | #endif 92 | 93 | /* C99 5.2.4.2.1: Added long long. 94 | C++11 18.3.3.2: same contents as the Standard C Library header . 95 | */ 96 | #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L 97 | 98 | #undef LLONG_MIN 99 | #undef LLONG_MAX 100 | #undef ULLONG_MAX 101 | 102 | #define LLONG_MAX __LONG_LONG_MAX__ 103 | #define LLONG_MIN (-__LONG_LONG_MAX__-1LL) 104 | #define ULLONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL) 105 | #endif 106 | 107 | /* LONG_LONG_MIN/LONG_LONG_MAX/ULONG_LONG_MAX are a GNU extension. It's too bad 108 | that we don't have something like #pragma poison that could be used to 109 | deprecate a macro - the code should just use LLONG_MAX and friends. 110 | */ 111 | #if defined(__GNU_LIBRARY__) ? defined(__USE_GNU) : !defined(__STRICT_ANSI__) 112 | 113 | #undef LONG_LONG_MIN 114 | #undef LONG_LONG_MAX 115 | #undef ULONG_LONG_MAX 116 | 117 | #define LONG_LONG_MAX __LONG_LONG_MAX__ 118 | #define LONG_LONG_MIN (-__LONG_LONG_MAX__-1LL) 119 | #define ULONG_LONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL) 120 | #endif 121 | 122 | #endif /* __CLANG_LIMITS_H */ 123 | -------------------------------------------------------------------------------- /.github/workflows/support/build/action.yml: -------------------------------------------------------------------------------- 1 | inputs: 2 | action: 3 | description: "The action to run, i.e. test/release" 4 | arch: 5 | description: "The architecture" 6 | docker_arch: 7 | description: "The architecture as it's named in Docker" 8 | target_operating_system: 9 | description: "The target operating system" 10 | target_version: 11 | description: "The target operating system version" 12 | target_triple: 13 | description: "The target triple" 14 | release_platform: 15 | description: "The name of the platform used for releases" 16 | llvm: 17 | description: "The version of LLVM" 18 | cross_platform_actions: 19 | description: "Indicates if the Cross Platform Action should be used" 20 | docker: 21 | description: "Indicates if Docker should be used" 22 | compiler: 23 | description: "The compiler to use" 24 | 25 | runs: 26 | using: "composite" 27 | steps: 28 | - name: Download LLVM 29 | if: runner.os != 'Windows' 30 | shell: bash 31 | run: | 32 | curl -f -L -o llvm.tar.xz --retry 3 'https://github.com/jacob-carlborg/clang-builder/releases/download/v${{ inputs.llvm }}%2B0.0.2-rc2/llvm-${{ inputs.llvm }}-${{ inputs.target_triple }}.tar.xz' 33 | tar xf llvm.tar.xz 34 | 35 | - name: Download LLVM 36 | if: runner.os == 'Windows' 37 | shell: bash 38 | run: | 39 | curl -f -L -o llvm.7z --retry 3 'https://github.com/jacob-carlborg/clang-builder/releases/download/v${{ inputs.llvm }}%2B0.0.2-rc2/llvm-${{ inputs.llvm }}-${{ inputs.target_triple }}.7z' 40 | 7z x llvm.7z 41 | 42 | # - name: Setup tmate session 43 | # uses: mxschmitt/action-tmate@v3 44 | # with: 45 | # limit-access-to-actor: true 46 | 47 | - name: Test 48 | if: ${{ !inputs.cross_platform_actions && !inputs.docker }} 49 | shell: bash 50 | env: 51 | DSTEP_LLVM_VERSION: ${{ inputs.llvm }} 52 | DSTEP_COMPILER: ${{ inputs.compiler }} 53 | DSTEP_RELEASE_PLATFORM: ${{ inputs.release_platform }} 54 | DSTEP_TARGET_TRIPLE: ${{ inputs.target_triple }} 55 | run: ./ci.sh ${{ inputs.action }} 56 | 57 | - name: Test 58 | if: inputs.cross_platform_actions 59 | env: 60 | DSTEP_LLVM_VERSION: ${{ inputs.llvm }} 61 | DSTEP_COMPILER: ${{ inputs.compiler }} 62 | DSTEP_RELEASE_PLATFORM: ${{ inputs.release_platform }} 63 | DSTEP_TARGET_TRIPLE: ${{ inputs.target_triple }} 64 | uses: cross-platform-actions/action@v0.23.0 65 | with: 66 | shell: bash 67 | operating_system: ${{ inputs.target_operating_system }} 68 | version: ${{ inputs.target_version }} 69 | environment_variables: >- 70 | DSTEP_LLVM_VERSION 71 | DSTEP_COMPILER 72 | DSTEP_RELEASE_PLATFORM 73 | DSTEP_TARGET_TRIPLE 74 | run: | 75 | sudo pkg install -y llvm19 git gnupg 76 | ./ci.sh ${{ inputs.action }} 77 | 78 | - name: Set up QEMU 79 | if: inputs.docker && inputs.arch != 'x86_64' 80 | uses: docker/setup-qemu-action@v1 81 | with: 82 | platforms: ${{ inputs.arch }} 83 | 84 | - name: Run Tests in Docker 85 | if: inputs.docker 86 | shell: bash 87 | env: 88 | DSTEP_LLVM_VERSION: ${{ inputs.llvm }} 89 | DSTEP_COMPILER: ${{ inputs.compiler }} 90 | DSTEP_RELEASE_PLATFORM: ${{ inputs.release_platform }} 91 | DSTEP_TARGET_TRIPLE: ${{ inputs.target_triple }} 92 | run: | 93 | docker run \ 94 | --rm \ 95 | -v $(pwd):/${{ github.workspace }} \ 96 | -w ${{ github.workspace }} \ 97 | -e DSTEP_LLVM_VERSION=${{ env.DSTEP_LLVM_VERSION }} \ 98 | -e DSTEP_COMPILER=${{ env.DSTEP_COMPILER }} \ 99 | -e DSTEP_RELEASE_PLATFORM=${{ env.DSTEP_RELEASE_PLATFORM }} \ 100 | -e DSTEP_TARGET_TRIPLE=${{ env.DSTEP_TARGET_TRIPLE }} \ 101 | --platform linux/${{ inputs.docker_arch || inputs.arch }} \ 102 | alpine:edge \ 103 | apk add --no-cache git curl bash && \ 104 | ./ci.sh ${{ inputs.action }} 105 | -------------------------------------------------------------------------------- /resources/stddef.h: -------------------------------------------------------------------------------- 1 | /*===---- stddef.h - Basic type definitions --------------------------------=== 2 | * 3 | * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | * See https://llvm.org/LICENSE.txt for license information. 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | * 7 | *===-----------------------------------------------------------------------=== 8 | */ 9 | 10 | #if !defined(__STDDEF_H) || defined(__need_ptrdiff_t) || \ 11 | defined(__need_size_t) || defined(__need_wchar_t) || \ 12 | defined(__need_NULL) || defined(__need_wint_t) 13 | 14 | #if !defined(__need_ptrdiff_t) && !defined(__need_size_t) && \ 15 | !defined(__need_wchar_t) && !defined(__need_NULL) && \ 16 | !defined(__need_wint_t) 17 | /* Always define miscellaneous pieces when modules are available. */ 18 | #if !__has_feature(modules) 19 | #define __STDDEF_H 20 | #endif 21 | #define __need_ptrdiff_t 22 | #define __need_size_t 23 | #define __need_wchar_t 24 | #define __need_NULL 25 | #define __need_STDDEF_H_misc 26 | /* __need_wint_t is intentionally not defined here. */ 27 | #endif 28 | 29 | #if defined(__need_ptrdiff_t) 30 | #if !defined(_PTRDIFF_T) || __has_feature(modules) 31 | /* Always define ptrdiff_t when modules are available. */ 32 | #if !__has_feature(modules) 33 | #define _PTRDIFF_T 34 | #endif 35 | typedef __PTRDIFF_TYPE__ ptrdiff_t; 36 | #endif 37 | #undef __need_ptrdiff_t 38 | #endif /* defined(__need_ptrdiff_t) */ 39 | 40 | #if defined(__need_size_t) 41 | #if !defined(_SIZE_T) || __has_feature(modules) 42 | /* Always define size_t when modules are available. */ 43 | #if !__has_feature(modules) 44 | #define _SIZE_T 45 | #endif 46 | typedef __SIZE_TYPE__ size_t; 47 | #endif 48 | #undef __need_size_t 49 | #endif /*defined(__need_size_t) */ 50 | 51 | #if defined(__need_STDDEF_H_misc) 52 | /* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is 53 | * enabled. */ 54 | #if (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1 && \ 55 | !defined(_RSIZE_T)) || __has_feature(modules) 56 | /* Always define rsize_t when modules are available. */ 57 | #if !__has_feature(modules) 58 | #define _RSIZE_T 59 | #endif 60 | typedef __SIZE_TYPE__ rsize_t; 61 | #endif 62 | #endif /* defined(__need_STDDEF_H_misc) */ 63 | 64 | #if defined(__need_wchar_t) 65 | #if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED) 66 | /* Always define wchar_t when modules are available. */ 67 | #if !defined(_WCHAR_T) || __has_feature(modules) 68 | #if !__has_feature(modules) 69 | #define _WCHAR_T 70 | #if defined(_MSC_EXTENSIONS) 71 | #define _WCHAR_T_DEFINED 72 | #endif 73 | #endif 74 | typedef __WCHAR_TYPE__ wchar_t; 75 | #endif 76 | #endif 77 | #undef __need_wchar_t 78 | #endif /* defined(__need_wchar_t) */ 79 | 80 | #if defined(__need_NULL) 81 | #undef NULL 82 | #ifdef __cplusplus 83 | # if !defined(__MINGW32__) && !defined(_MSC_VER) 84 | # define NULL __null 85 | # else 86 | # define NULL 0 87 | # endif 88 | #else 89 | # define NULL ((void*)0) 90 | #endif 91 | #ifdef __cplusplus 92 | #if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED) 93 | namespace std { typedef decltype(nullptr) nullptr_t; } 94 | using ::std::nullptr_t; 95 | #endif 96 | #endif 97 | #undef __need_NULL 98 | #endif /* defined(__need_NULL) */ 99 | 100 | #if defined(__need_STDDEF_H_misc) 101 | #if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L 102 | #include "__stddef_max_align_t.h" 103 | #endif 104 | #define offsetof(t, d) __builtin_offsetof(t, d) 105 | #undef __need_STDDEF_H_misc 106 | #endif /* defined(__need_STDDEF_H_misc) */ 107 | 108 | /* Some C libraries expect to see a wint_t here. Others (notably MinGW) will use 109 | __WINT_TYPE__ directly; accommodate both by requiring __need_wint_t */ 110 | #if defined(__need_wint_t) 111 | /* Always define wint_t when modules are available. */ 112 | #if !defined(_WINT_T) || __has_feature(modules) 113 | #if !__has_feature(modules) 114 | #define _WINT_T 115 | #endif 116 | typedef __WINT_TYPE__ wint_t; 117 | #endif 118 | #undef __need_wint_t 119 | #endif /* __need_wint_t */ 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /tests/unit/TypeInferenceTests.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: October 13, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import core.exception; 8 | 9 | import std.container.dlist; 10 | import std.variant; 11 | 12 | import Common; 13 | import Assert; 14 | 15 | import dstep.translator.MacroDefinition; 16 | 17 | unittest 18 | { 19 | assertTranslates(q"C 20 | #define FOO(x) BAR(int) 21 | C", q"D 22 | extern (C): 23 | 24 | extern (D) auto FOO(T)(auto ref T x) 25 | { 26 | return BAR(int); 27 | } 28 | D"); 29 | } 30 | 31 | unittest 32 | { 33 | assertTranslates(q"C 34 | #define BAR(x) 0 35 | #define FOO(x) BAR(int) 36 | C", q"D 37 | extern (C): 38 | 39 | extern (D) int BAR(x)() 40 | { 41 | return 0; 42 | } 43 | 44 | extern (D) auto FOO(T)(auto ref T x) 45 | { 46 | return BAR!int(); 47 | } 48 | D"); 49 | } 50 | 51 | unittest 52 | { 53 | assertTranslates(q"C 54 | #define BAR(x, y, z) x * y * sizeof(z) 55 | 56 | #define BAZ BAR(0, 1, float) 57 | C", q"D 58 | extern (C): 59 | 60 | extern (D) auto BAR(z, T0, T1)(auto ref T0 x, auto ref T1 y) 61 | { 62 | return x * y * z.sizeof; 63 | } 64 | 65 | enum BAZ = BAR!float(0, 1); 66 | D"); 67 | 68 | } 69 | 70 | unittest 71 | { 72 | assertTranslates(q"C 73 | typedef struct { } foo_t; 74 | 75 | #define BAR(x, y, z) x * y * sizeof(z) 76 | 77 | #define BAZ BAR(0, 1, foo_t) 78 | C", q"D 79 | extern (C): 80 | 81 | struct foo_t 82 | { 83 | } 84 | 85 | extern (D) auto BAR(z, T0, T1)(auto ref T0 x, auto ref T1 y) 86 | { 87 | return x * y * z.sizeof; 88 | } 89 | 90 | enum BAZ = BAR!foo_t(0, 1); 91 | D"); 92 | 93 | } 94 | 95 | unittest 96 | { 97 | assertTranslates(q"C 98 | typedef unsigned int __u32; 99 | 100 | #define BAR(x) sizeof(x) 101 | 102 | #define BAZ BAR(__u32) 103 | C", q"D 104 | extern (C): 105 | 106 | extern (D) size_t BAR(x)() 107 | { 108 | return x.sizeof; 109 | } 110 | 111 | enum BAZ = BAR!uint(); 112 | D"); 113 | 114 | } 115 | 116 | unittest 117 | { 118 | assertTranslates(q"C 119 | #define FOO() 0 120 | 121 | #define BAR(x) BAZ(0, 1, x) 122 | 123 | #define BAZ(x, y, z) sizeof(z) * x * y 124 | 125 | #define QUX(x) BAR(float) 126 | C", q"D 127 | extern (C): 128 | 129 | extern (D) int FOO() 130 | { 131 | return 0; 132 | } 133 | 134 | extern (D) auto BAR(x)() 135 | { 136 | return BAZ!x(0, 1); 137 | } 138 | 139 | extern (D) auto BAZ(z, T0, T1)(auto ref T0 x, auto ref T1 y) 140 | { 141 | return z.sizeof * x * y; 142 | } 143 | 144 | extern (D) auto QUX(T)(auto ref T x) 145 | { 146 | return BAR!float(); 147 | } 148 | D"); 149 | 150 | } 151 | 152 | unittest 153 | { 154 | assertTranslates(q"C 155 | #define FOO(type) sizeof(type) 156 | 157 | #define BAR FOO(unsigned int) 158 | #define BAZ FOO(unsigned short) 159 | #define QUX FOO(long) 160 | C", q"D 161 | import core.stdc.config; 162 | 163 | extern (C): 164 | 165 | extern (D) size_t FOO(type)() 166 | { 167 | return type.sizeof; 168 | } 169 | 170 | enum BAR = FOO!uint(); 171 | enum BAZ = FOO!ushort(); 172 | enum QUX = FOO!c_long(); 173 | D"); 174 | } 175 | 176 | unittest 177 | { 178 | assertTranslates(q"C 179 | #define FOO(a, b, c, d) 0 180 | 181 | #define BAR(t) sizeof(t) 182 | 183 | #define BAZ(x2,x3) FOO(x0,(x2),(x3),0) 184 | #define QUX(x2,x3,type) FOO(x4,(x2),(x3),(BAR(type))) 185 | 186 | #define ENUM0 QUX('a', 0, char) 187 | #define ENUM1 QUX('b', 1, short) 188 | #define ENUM2 QUX('c', 2, int) 189 | C", q"D 190 | extern (C): 191 | 192 | extern (D) int FOO(T0, T1, T2, T3)(auto ref T0 a, auto ref T1 b, auto ref T2 c, auto ref T3 d) 193 | { 194 | return 0; 195 | } 196 | 197 | extern (D) size_t BAR(t)() 198 | { 199 | return t.sizeof; 200 | } 201 | 202 | extern (D) auto BAZ(T0, T1)(auto ref T0 x2, auto ref T1 x3) 203 | { 204 | return FOO(x0, x2, x3, 0); 205 | } 206 | 207 | extern (D) auto QUX(type, T0, T1)(auto ref T0 x2, auto ref T1 x3) 208 | { 209 | return FOO(x4, x2, x3, BAR!type()); 210 | } 211 | 212 | enum ENUM0 = QUX!char('a', 0); 213 | enum ENUM1 = QUX!short('b', 1); 214 | enum ENUM2 = QUX!int('c', 2); 215 | D"); 216 | 217 | } 218 | -------------------------------------------------------------------------------- /tests/unit/issues/Issue58.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jul 27, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | 8 | import Common; 9 | 10 | import clang.Util; 11 | 12 | import dstep.translator.Options; 13 | 14 | // Fix 58: Symbol selection. 15 | 16 | void assertSkipSymbols( 17 | string[] symbols, 18 | string source, 19 | string expected, 20 | string file = __FILE__, 21 | size_t line = __LINE__) 22 | { 23 | Options options; 24 | 25 | options.skipSymbols = setFromList(symbols); 26 | 27 | assertTranslates(source, expected, options, false, file, line); 28 | } 29 | 30 | void assertSkipdefSymbols( 31 | string[] symbols, 32 | string source, 33 | string expected, 34 | string file = __FILE__, 35 | size_t line = __LINE__) 36 | { 37 | Options options; 38 | 39 | options.skipDefinitions = setFromList(symbols); 40 | 41 | assertTranslates(source, expected, options, false, file, line); 42 | } 43 | 44 | unittest 45 | { 46 | // Skip variable. 47 | assertSkipSymbols( 48 | ["foo"], q"C 49 | int foo; 50 | int bar; 51 | C", q"D 52 | extern (C): 53 | 54 | extern __gshared int bar; 55 | D"); 56 | 57 | // Skip function. 58 | assertSkipSymbols( 59 | ["foo"], q"C 60 | int foo(int a, int b, int c); 61 | int bar(int a, int b, int c); 62 | C", q"D 63 | extern (C): 64 | 65 | int bar (int a, int b, int c); 66 | D"); 67 | 68 | // Skip struct. 69 | assertSkipSymbols( 70 | ["Foo"], q"C 71 | struct Foo { 72 | }; 73 | 74 | struct Bar { 75 | }; 76 | C", q"D 77 | extern (C): 78 | 79 | struct Bar 80 | { 81 | } 82 | D"); 83 | 84 | // Skip union. 85 | assertSkipSymbols( 86 | ["Foo"], q"C 87 | union Foo { 88 | }; 89 | 90 | union Bar { 91 | }; 92 | C", q"D 93 | extern (C): 94 | 95 | union Bar 96 | { 97 | } 98 | D"); 99 | 100 | // Skip typedef. 101 | assertSkipSymbols( 102 | ["Baz"], q"C 103 | struct Foo { }; 104 | typedef struct Foo Bar; 105 | typedef struct Foo Baz; 106 | C", q"D 107 | extern (C): 108 | 109 | struct Foo 110 | { 111 | } 112 | 113 | alias Bar = Foo; 114 | D"); 115 | 116 | // Skip macro-definition. 117 | assertSkipSymbols( 118 | ["FOO", "BAZ"], q"C 119 | #define FOO 42 120 | #define BAR 31415 121 | #define BAZ(x) x * 2 122 | #define QUX(x) x == 42 ? 0 : 1 123 | C", q"D 124 | extern (C): 125 | 126 | enum BAR = 31415; 127 | 128 | extern (D) int QUX(T)(auto ref T x) 129 | { 130 | return x == 42 ? 0 : 1; 131 | } 132 | D"); 133 | 134 | } 135 | 136 | unittest 137 | { 138 | assertSkipdefSymbols( 139 | ["Foo"], q"C 140 | struct Foo { 141 | int foo; 142 | int bar; 143 | }; 144 | 145 | struct Bar { 146 | int baz; 147 | int qux; 148 | }; 149 | C", q"D 150 | extern (C): 151 | 152 | struct Foo; 153 | 154 | struct Bar 155 | { 156 | int baz; 157 | int qux; 158 | } 159 | D"); 160 | 161 | assertSkipdefSymbols( 162 | ["Foo"], q"C 163 | typedef struct Foo { 164 | int foo; 165 | int bar; 166 | } Foo; 167 | 168 | typedef struct Bar { 169 | int baz; 170 | int qux; 171 | } Bar; 172 | C", q"D 173 | extern (C): 174 | 175 | struct Foo; 176 | 177 | struct Bar 178 | { 179 | int baz; 180 | int qux; 181 | } 182 | D"); 183 | 184 | assertSkipdefSymbols( 185 | ["Foo"], q"C 186 | typedef struct { 187 | int foo; 188 | int bar; 189 | } Foo; 190 | 191 | typedef struct { 192 | int baz; 193 | int qux; 194 | } Bar; 195 | C", q"D 196 | extern (C): 197 | 198 | struct Foo; 199 | 200 | struct Bar 201 | { 202 | int baz; 203 | int qux; 204 | } 205 | D"); 206 | 207 | assertSkipdefSymbols( 208 | ["Foo"], q"C 209 | typedef struct Foo { 210 | int foo; 211 | int bar; 212 | } Bar; 213 | C", q"D 214 | extern (C): 215 | 216 | struct Foo; 217 | alias Bar = Foo; 218 | D"); 219 | 220 | } 221 | 222 | unittest 223 | { 224 | assertSkipSymbols( 225 | ["Foo"], q"C 226 | typedef struct Foo { 227 | int foo; 228 | int bar; 229 | } Bar; 230 | C", q"D 231 | extern (C): 232 | 233 | D"); 234 | 235 | } 236 | -------------------------------------------------------------------------------- /tests/unit/FormattingUnitTest.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: September 16, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import std.stdio; 8 | import Common; 9 | import dstep.translator.Translator; 10 | 11 | // Long function declarations should be broken to multiple lines. 12 | unittest 13 | { 14 | assertTranslates(q"C 15 | void very_long_function_declaration(double way_too_long_argument, 16 | double another_long_argument); 17 | C", 18 | q"D 19 | extern (C): 20 | 21 | void very_long_function_declaration ( 22 | double way_too_long_argument, 23 | double another_long_argument); 24 | D"); 25 | 26 | } 27 | 28 | // Long function pointer declarations should be broken to multiple lines. 29 | unittest 30 | { 31 | assertTranslates(q"C 32 | typedef void (*very_long_function_pointer)(int foofoofoo, 33 | int barbarbarbar, 34 | unsigned bazbazbaz, 35 | unsigned quxquxqux0, 36 | unsigned quxquxqux1); 37 | C", 38 | q"D 39 | extern (C): 40 | 41 | alias very_long_function_pointer = void function ( 42 | int foofoofoo, 43 | int barbarbarbar, 44 | uint bazbazbaz, 45 | uint quxquxqux0, 46 | uint quxquxqux1); 47 | D"); 48 | 49 | } 50 | 51 | // Long nested function pointer declarations should be broken to multiple lines. 52 | unittest 53 | { 54 | assertTranslates(q"C 55 | typedef struct { 56 | void (*very_long_function_pointer)(int foofoofoo, 57 | int barbarbarbar, 58 | unsigned bazbazbaz, 59 | unsigned quxquxqux0, 60 | unsigned quxquxqux1); 61 | } foo_t; 62 | C", 63 | q"D 64 | extern (C): 65 | 66 | struct foo_t 67 | { 68 | void function ( 69 | int foofoofoo, 70 | int barbarbarbar, 71 | uint bazbazbaz, 72 | uint quxquxqux0, 73 | uint quxquxqux1) very_long_function_pointer; 74 | } 75 | D"); 76 | 77 | } 78 | 79 | // Long function declarations shouldn't be broken, if they aren't in original. 80 | unittest 81 | { 82 | assertTranslates(q"C 83 | void very_long_function_declaration(double way_too_long_argument, double another_long_argument); 84 | C", 85 | q"D 86 | extern (C): 87 | 88 | void very_long_function_declaration (double way_too_long_argument, double another_long_argument); 89 | D"); 90 | 91 | } 92 | 93 | // Long function declarations shouldn't be broken, if disabled in options. 94 | unittest 95 | { 96 | auto source = q"C 97 | void very_long_function_declaration(double way_too_long_argument, 98 | double another_long_argument); 99 | 100 | void (*very_long_function_pointer)(double way_too_long_argument, 101 | double another_long_argument); 102 | C"; 103 | 104 | Options options; 105 | options.singleLineFunctionSignatures = true; 106 | 107 | assertTranslates(source, q"D 108 | extern (C): 109 | 110 | void very_long_function_declaration (double way_too_long_argument, double another_long_argument); 111 | 112 | extern __gshared void function (double way_too_long_argument, double another_long_argument) very_long_function_pointer; 113 | D", options); 114 | 115 | options.singleLineFunctionSignatures = false; 116 | 117 | assertTranslates(source, q"D 118 | extern (C): 119 | 120 | void very_long_function_declaration ( 121 | double way_too_long_argument, 122 | double another_long_argument); 123 | 124 | extern __gshared void function ( 125 | double way_too_long_argument, 126 | double another_long_argument) very_long_function_pointer; 127 | D", options); 128 | 129 | } 130 | 131 | // Test not putting a space after a function name. 132 | unittest 133 | { 134 | Options options; 135 | options.spaceAfterFunctionName = false; 136 | 137 | assertTranslates(q"C 138 | void very_long_function_declaration(double way_too_long_argument, double another_long_argument); 139 | C", 140 | q"D 141 | extern (C): 142 | 143 | void very_long_function_declaration(double way_too_long_argument, double another_long_argument); 144 | D", options); 145 | 146 | } 147 | -------------------------------------------------------------------------------- /tests/unit/BitFieldsTests.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: October 22, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module tests.unit.BitFieldsTests; 8 | 9 | import Common; 10 | 11 | unittest 12 | { 13 | assertTranslates(q"C 14 | struct Foo 15 | { 16 | int x : 4; 17 | }; 18 | 19 | C",q"D 20 | extern (C): 21 | 22 | struct Foo 23 | { 24 | import std.bitmanip : bitfields; 25 | 26 | mixin(bitfields!( 27 | int, "x", 4, 28 | uint, "", 4)); 29 | } 30 | D"); 31 | 32 | } 33 | 34 | unittest 35 | { 36 | assertTranslates(q"C 37 | struct Foo 38 | { 39 | int x : 8; 40 | }; 41 | 42 | C",q"D 43 | extern (C): 44 | 45 | struct Foo 46 | { 47 | import std.bitmanip : bitfields; 48 | mixin(bitfields!(int, "x", 8)); 49 | } 50 | D"); 51 | 52 | } 53 | 54 | 55 | unittest 56 | { 57 | assertTranslates(q"C 58 | struct bitfield { 59 | unsigned int one : 4; 60 | unsigned int two : 8; 61 | unsigned int : 4; 62 | }; 63 | C",q"D 64 | extern (C): 65 | 66 | struct bitfield 67 | { 68 | import std.bitmanip : bitfields; 69 | 70 | mixin(bitfields!( 71 | uint, "one", 4, 72 | uint, "two", 8, 73 | uint, "", 4)); 74 | } 75 | D"); 76 | } 77 | 78 | unittest 79 | { 80 | assertTranslates(q"C 81 | struct Foo { 82 | unsigned char a : 3, : 2, b : 6, c : 2; 83 | }; 84 | C",q"D 85 | extern (C): 86 | 87 | struct Foo 88 | { 89 | import std.bitmanip : bitfields; 90 | 91 | mixin(bitfields!( 92 | ubyte, "a", 3, 93 | ubyte, "", 2, 94 | ubyte, "b", 6, 95 | ubyte, "c", 2, 96 | uint, "", 3)); 97 | } 98 | D"); 99 | 100 | }; 101 | 102 | unittest 103 | { 104 | assertTranslates(q"C 105 | struct Foo { 106 | short a : 4; 107 | char b; 108 | }; 109 | C",q"D 110 | extern (C): 111 | 112 | struct Foo 113 | { 114 | import std.bitmanip : bitfields; 115 | 116 | mixin(bitfields!( 117 | short, "a", 4, 118 | uint, "", 4)); 119 | 120 | char b; 121 | } 122 | D"); 123 | 124 | }; 125 | 126 | unittest 127 | { 128 | assertTranslates(q"C 129 | struct Foo { 130 | short a; 131 | char b : 7; 132 | char c[1]; 133 | }; 134 | C",q"D 135 | extern (C): 136 | 137 | struct Foo 138 | { 139 | import std.bitmanip : bitfields; 140 | 141 | short a; 142 | 143 | mixin(bitfields!( 144 | char, "b", 7, 145 | uint, "", 1)); 146 | 147 | char[1] c; 148 | } 149 | D"); 150 | 151 | }; 152 | 153 | unittest 154 | { 155 | assertTranslates(q"C 156 | struct Foo { 157 | short a; 158 | char b; 159 | int c : 1; 160 | int d : 4; 161 | int e : 7; 162 | }; 163 | C",q"D 164 | extern (C): 165 | 166 | struct Foo 167 | { 168 | import std.bitmanip : bitfields; 169 | 170 | short a; 171 | char b; 172 | 173 | mixin(bitfields!( 174 | int, "c", 1, 175 | int, "d", 4, 176 | int, "e", 7, 177 | uint, "", 4)); 178 | } 179 | D"); 180 | 181 | }; 182 | 183 | unittest 184 | { 185 | assertTranslates(q"C 186 | struct Foo { 187 | short a; 188 | int b : 1; 189 | int c : 4; 190 | int d : 3; 191 | int e : 7; 192 | int f : 25; 193 | char g; 194 | }; 195 | C",q"D 196 | extern (C): 197 | 198 | struct Foo 199 | { 200 | import std.bitmanip : bitfields; 201 | 202 | short a; 203 | 204 | mixin(bitfields!( 205 | int, "b", 1, 206 | int, "c", 4, 207 | int, "d", 3, 208 | int, "e", 7, 209 | int, "f", 25, 210 | uint, "", 24)); 211 | 212 | char g; 213 | } 214 | D"); 215 | 216 | }; 217 | 218 | unittest 219 | { 220 | assertTranslates(q"C 221 | struct Foo { 222 | short a; 223 | int b : 1; 224 | int c : 4; 225 | int d : 3; 226 | long e; 227 | int f : 7; 228 | int g : 25; 229 | char h; 230 | }; 231 | C",q"D 232 | import core.stdc.config; 233 | 234 | extern (C): 235 | 236 | struct Foo 237 | { 238 | import std.bitmanip : bitfields; 239 | 240 | short a; 241 | 242 | mixin(bitfields!( 243 | int, "b", 1, 244 | int, "c", 4, 245 | int, "d", 3)); 246 | 247 | c_long e; 248 | 249 | mixin(bitfields!( 250 | int, "f", 7, 251 | int, "g", 25)); 252 | 253 | char h; 254 | } 255 | D"); 256 | 257 | }; 258 | -------------------------------------------------------------------------------- /tests/unit/Assert.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Jun 30, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | import core.exception; 8 | 9 | import clang.c.Index; 10 | import clang.Type; 11 | import clang.Util; 12 | 13 | import Common; 14 | 15 | import dstep.translator.CommentIndex; 16 | import dstep.translator.Context; 17 | import dstep.translator.IncludeHandler; 18 | import dstep.translator.MacroDefinition; 19 | import dstep.translator.MacroParser; 20 | import dstep.translator.Output; 21 | import dstep.translator.Translator; 22 | import dstep.translator.Type; 23 | import dstep.translator.TypeInference; 24 | 25 | void assertTranslatesMacroDefinition( 26 | string source, 27 | string expected, 28 | string file = __FILE__, 29 | size_t line = __LINE__) 30 | { 31 | auto translUnit = makeTranslationUnit(source); 32 | 33 | Options options; 34 | Output output = new Output; 35 | 36 | Context context = new Context(translUnit, options); 37 | 38 | auto children = translUnit.cursor.children(true); 39 | 40 | if (children.length != 1) 41 | throw new AssertError("Assertion failure", file, line); 42 | 43 | auto definitions = inferMacroSignatures(context); 44 | 45 | if (auto definition = children[0].spelling in definitions) 46 | translateMacroDefinition(output, context, *definition); 47 | 48 | assertEq(expected, output.data, false, file, line); 49 | } 50 | 51 | void assertTranslatesMacroExpression( 52 | string source, 53 | string expected, 54 | string file = __FILE__, 55 | size_t line = __LINE__) 56 | { 57 | auto translUnit = makeTranslationUnit(source); 58 | 59 | Options options; 60 | Output output = new Output; 61 | 62 | Context context = new Context(translUnit, options); 63 | 64 | auto children = translUnit.cursor.children(true); 65 | 66 | if (children.length != 1) 67 | throw new AssertError("Assertion failure", file, line); 68 | 69 | Cursor cursor = children[0]; 70 | 71 | assert(cursor.kind == CXCursorKind.macroDefinition); 72 | 73 | auto tokens = cursor.tokens; 74 | 75 | auto definition = parsePartialMacroDefinition(tokens, context.typeNames); 76 | 77 | auto expressionContext = ExpressionContext.make(context); 78 | 79 | string actual = null; 80 | 81 | if (definition !is null) 82 | { 83 | if (definition.expr.hasValue) 84 | actual = definition.expr.debraced.translate(expressionContext); 85 | } 86 | 87 | assertEq(expected, actual, false, file, line); 88 | } 89 | 90 | void assertDoesntParseMacroExpression( 91 | string source, 92 | string file = __FILE__, 93 | size_t line = __LINE__) 94 | { 95 | auto translUnit = makeTranslationUnit(source); 96 | 97 | Options options; 98 | Output output = new Output; 99 | 100 | Context context = new Context(translUnit, options); 101 | 102 | auto children = translUnit.cursor.children(true); 103 | 104 | if (children.length != 1) 105 | throw new AssertError("Assertion failure", file, line); 106 | 107 | Cursor cursor = children[0]; 108 | 109 | assert(cursor.kind == CXCursorKind.macroDefinition); 110 | 111 | auto tokens = cursor.tokens; 112 | 113 | auto definition = parsePartialMacroDefinition(tokens, context.typeNames); 114 | 115 | if (definition !is null) 116 | throw new AssertError("Assertion failure", file, line); 117 | } 118 | 119 | Type parseTypeName(string source) 120 | { 121 | Cursor[string] table; 122 | auto tokens = tokenize(source); 123 | return dstep.translator.MacroParser.parseTypeName(tokens, table); 124 | } 125 | 126 | void assertParsedTypeHasKind( 127 | string source, 128 | CXTypeKind kind, 129 | string file = __FILE__, 130 | size_t line = __LINE__) 131 | { 132 | import core.exception; 133 | 134 | Type type = parseTypeName(source); 135 | 136 | if (type.kind != kind) 137 | throw new AssertError("Assertion failure", file, line); 138 | } 139 | 140 | void assertTypeIsntParsed( 141 | string source, 142 | string file = __FILE__, 143 | size_t line = __LINE__) 144 | { 145 | import core.exception; 146 | 147 | Type type = parseTypeName(source); 148 | 149 | if (type.isValid) 150 | throw new AssertError("Assertion failure", file, line); 151 | } 152 | -------------------------------------------------------------------------------- /dstep/translator/Options.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: May 21, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.translator.Options; 8 | 9 | import clang.Util; 10 | 11 | import dstep.translator.ConvertCase; 12 | 13 | enum Language 14 | { 15 | c, 16 | objC 17 | } 18 | 19 | enum CollisionAction 20 | { 21 | ignore, 22 | rename, 23 | abort 24 | } 25 | 26 | struct Options 27 | { 28 | import clang.Cursor: Cursor; 29 | 30 | string[] inputFiles; 31 | string inputFile; 32 | string outputFile; 33 | Language language = Language.c; 34 | string packageName; 35 | bool enableComments = true; 36 | bool publicSubmodules = false; 37 | bool normalizeModules = false; 38 | bool keepUntranslatable = false; 39 | bool reduceAliases = true; 40 | bool translateMacros = true; 41 | bool portableWCharT = true; 42 | bool zeroParamIsVararg = false; 43 | bool singleLineFunctionSignatures = false; 44 | bool spaceAfterFunctionName = true; 45 | bool aliasEnumMembers = false; 46 | bool renameEnumMembers = false; 47 | Set!string skipDefinitions; 48 | Set!string skipSymbols; 49 | bool printDiagnostics = true; 50 | CollisionAction collisionAction = CollisionAction.rename; 51 | const(string)[] globalAttributes; 52 | const(string)[] globalImports; 53 | const(string)[] publicGlobalImports; 54 | bool delegate(ref const(Cursor)) isWantedCursorForTypedefs; 55 | 56 | string toString() const 57 | { 58 | import std.format : format; 59 | 60 | return format( 61 | "Options(outputFile = %s, language = %s, enableComments = %s, " ~ 62 | "reduceAliases = %s, portableWCharT = %s)", 63 | outputFile, 64 | language, 65 | enableComments, 66 | reduceAliases, 67 | portableWCharT); 68 | } 69 | } 70 | 71 | string fullModuleName(string packageName, string path, bool normalize = true) 72 | { 73 | import std.algorithm; 74 | import std.path : baseName, stripExtension; 75 | import std.range; 76 | import std.uni; 77 | import std.utf; 78 | 79 | dchar replace(dchar c) 80 | { 81 | if (c == '_' || c.isWhite) 82 | return '_'; 83 | else if (c.isPunctuation) 84 | return '.'; 85 | else 86 | return c; 87 | } 88 | 89 | bool discard(dchar c) 90 | { 91 | return c.isAlphaNum || c == '_' || c == '.'; 92 | } 93 | 94 | bool equivalent(dchar a, dchar b) 95 | { 96 | return (a == '.' || a == '_') && (b == '.' || b == '_'); 97 | } 98 | 99 | auto moduleBaseName = stripExtension(baseName(path)); 100 | auto moduleName = moduleBaseName.map!replace.filter!discard.uniq!equivalent; 101 | 102 | 103 | if (normalize) 104 | { 105 | auto segments = moduleName.split!(x => x == '.'); 106 | auto normalized = segments.map!(x => x.toUTF8.toSnakeCase).join('.'); 107 | return only(packageName, normalized).join('.'); 108 | } 109 | else 110 | { 111 | return only(packageName, moduleName.toUTF8).join('.'); 112 | } 113 | } 114 | 115 | unittest 116 | { 117 | assert(fullModuleName("pkg", "foo") == "pkg.foo"); 118 | assert(fullModuleName("pkg", "Foo") == "pkg.foo"); 119 | assert(fullModuleName("pkg", "Foo.ext") == "pkg.foo"); 120 | 121 | assert(fullModuleName("pkg", "Foo-bar.ext") == "pkg.foo.bar"); 122 | assert(fullModuleName("pkg", "Foo_bar.ext") == "pkg.foo_bar"); 123 | assert(fullModuleName("pkg", "Foo@bar.ext") == "pkg.foo.bar"); 124 | assert(fullModuleName("pkg", "Foo~bar.ext") == "pkg.foo.bar"); 125 | assert(fullModuleName("pkg", "Foo bar.ext") == "pkg.foo_bar"); 126 | 127 | assert(fullModuleName("pkg", "Foo__bar.ext") == "pkg.foo_bar"); 128 | assert(fullModuleName("pkg", "Foo..bar.ext") == "pkg.foo.bar"); 129 | assert(fullModuleName("pkg", "Foo#$%#$%#bar.ext") == "pkg.foo.bar"); 130 | assert(fullModuleName("pkg", "Foo_#$%#$%#bar.ext") == "pkg.foo_bar"); 131 | 132 | assert(fullModuleName("pkg", "FooBarBaz.ext") == "pkg.foo_bar_baz"); 133 | assert(fullModuleName("pkg", "FooBar.BazQux.ext") == "pkg.foo_bar.baz_qux"); 134 | 135 | assert(fullModuleName("pkg", "FooBarBaz.ext", false) == "pkg.FooBarBaz"); 136 | assert(fullModuleName("pkg", "FooBar.BazQux.ext", false) == "pkg.FooBar.BazQux"); 137 | } 138 | -------------------------------------------------------------------------------- /dstep/translator/MacroIndex.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: Mar 08, 2016 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.translator.MacroIndex; 8 | 9 | import std.typecons; 10 | import std.algorithm; 11 | import std.range; 12 | 13 | import clang.c.Index; 14 | import clang.Cursor; 15 | import clang.SourceLocation; 16 | import clang.SourceRange; 17 | import clang.Token; 18 | import clang.TranslationUnit; 19 | 20 | import dstep.translator.Preprocessor; 21 | 22 | class MacroIndex 23 | { 24 | private TranslationUnit translUnit; 25 | private bool delegate (Cursor, Cursor) lessOp; 26 | private Cursor[] expansions; 27 | private Cursor[string] globalCursors_; 28 | public Directive[] directives; 29 | 30 | this(TranslationUnit translUnit) 31 | { 32 | this.translUnit = translUnit; 33 | 34 | auto expansionsAppender = appender!(Cursor[])(); 35 | 36 | foreach (cursor, parent; translUnit.cursor.all) 37 | { 38 | if (cursor.kind == CXCursorKind.macroExpansion) 39 | expansionsAppender.put(cursor); 40 | else if (!cursor.spelling.empty) 41 | globalCursors_[extendedSpelling(cursor)] = cursor; 42 | } 43 | 44 | lessOp = translUnit.relativeCursorLocationLessOp(); 45 | expansions = expansionsAppender.data.sort!((a, b) => lessOp(a, b)).array; 46 | directives = dstep.translator.Preprocessor.directives(translUnit); 47 | } 48 | 49 | static string extendedSpelling(Cursor cursor) 50 | { 51 | import std.format : format; 52 | 53 | switch (cursor.kind) 54 | { 55 | case CXCursorKind.structDecl: 56 | return format("struct %s", cursor.spelling); 57 | 58 | case CXCursorKind.unionDecl: 59 | return format("union %s", cursor.spelling); 60 | 61 | case CXCursorKind.enumDecl: 62 | return format("enum %s", cursor.spelling); 63 | 64 | default: 65 | return cursor.spelling; 66 | } 67 | } 68 | 69 | Cursor[] queryExpansion(Cursor cursor) const 70 | { 71 | import std.array; 72 | import std.algorithm.searching; 73 | 74 | auto expansionsSorted = expansions.assumeSorted!((a, b) => lessOp(a, b)); 75 | 76 | auto equal = expansionsSorted.equalRange(cursor); 77 | auto greater = expansionsSorted.upperBound(cursor); 78 | 79 | auto result = appender!(Cursor[])(); 80 | 81 | if (!equal.empty) 82 | result ~= equal.array; 83 | 84 | result ~= until 85 | !(itr => itr.file != cursor.file || 86 | itr.location.offset >= cursor.extent.end.offset) 87 | (greater, OpenRight.yes); 88 | 89 | return result.data; 90 | } 91 | 92 | 93 | Tuple!(bool, SourceLocation) includeGuardLocation() 94 | { 95 | import std.range.primitives : empty; 96 | 97 | static bool checkIfndef(ConditionalDirective directives, string identifier) 98 | { 99 | auto negation = directives.condition.peek!UnaryExpr; 100 | 101 | if (negation !is null && negation.operator == "!") 102 | { 103 | auto defined = negation.subexpr.peek!DefinedExpr; 104 | return defined !is null && defined.identifier == identifier; 105 | } 106 | 107 | return false; 108 | } 109 | 110 | if (!directives.empty) 111 | { 112 | if (directives[0].kind == DirectiveKind.pragmaOnce) 113 | { 114 | return Tuple!(bool, SourceLocation)(true, directives[0].extent.start); 115 | } 116 | else if (2 <= directives.length) 117 | { 118 | auto ifndef = cast (ConditionalDirective) directives[0]; 119 | auto define = cast (DefineDirective) directives[1]; 120 | auto endif = directives[$ - 1]; 121 | 122 | if (ifndef && define && 123 | ifndef.endif == endif && 124 | checkIfndef(ifndef, define.spelling)) 125 | return Tuple!(bool, SourceLocation)(true, ifndef.location); 126 | } 127 | } 128 | 129 | return Tuple!(bool, SourceLocation)(false, SourceLocation.empty); 130 | } 131 | 132 | Cursor[string] globalCursors() 133 | { 134 | return globalCursors_; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /dstep/driver/Application.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 | * Authors: Jacob Carlborg 4 | * Version: Initial created: Oct 1, 2011 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.driver.Application; 8 | 9 | import std.getopt; 10 | import std.stdio : writeln, stderr; 11 | import Path = std.path; 12 | import std.file; 13 | 14 | import clang.c.Index; 15 | 16 | import clang.Compiler; 17 | import clang.Index; 18 | import clang.TranslationUnit; 19 | import clang.Util; 20 | 21 | import dstep.Configuration; 22 | import dstep.translator.Options; 23 | import dstep.core.Exceptions; 24 | import dstep.translator.Options; 25 | import dstep.translator.Translator; 26 | 27 | class Application 28 | { 29 | private 30 | { 31 | Configuration config; 32 | } 33 | 34 | public this (Configuration config) 35 | { 36 | this.config = config; 37 | } 38 | 39 | public void run () 40 | { 41 | import std.exception : enforce; 42 | import std.range; 43 | 44 | enforce!DStepException(config.inputFiles.length > 0, 45 | "dstep: error: must supply at least one input file\n"); 46 | 47 | enforceInputFilesExist(config); 48 | 49 | auto translationUnits = makeTranslationUnits(config); 50 | 51 | enforceTranslationUnitsCompiled(translationUnits); 52 | 53 | auto inputFiles = config.inputFiles; 54 | auto outputFiles = makeOutputFiles(config); 55 | 56 | foreach (tuple; zip(inputFiles, outputFiles, translationUnits)) 57 | { 58 | string outputDirectory = Path.dirName(tuple[1]); 59 | 60 | if (!exists(outputDirectory)) 61 | mkdirRecurse(outputDirectory); 62 | 63 | Options options = this.config.toOptions(tuple[0], tuple[1]); 64 | 65 | auto translator = new Translator(tuple[2], options); 66 | translator.translate; 67 | } 68 | } 69 | 70 | static void enforceInputFilesExist(const Configuration config) 71 | { 72 | import std.exception : enforce; 73 | import std.format : format; 74 | 75 | foreach (inputFile; config.inputFiles) 76 | { 77 | enforce!DStepException( 78 | exists(inputFile), 79 | format("dstep: error: file '%s' doesn't exist\n", inputFile)); 80 | 81 | enforce!DStepException( 82 | isFile(inputFile), 83 | format("dstep: error: '%s' is not a file\n", inputFile)); 84 | } 85 | } 86 | 87 | void enforceTranslationUnitsCompiled(TranslationUnit[] translationUnits) 88 | { 89 | import std.array : Appender; 90 | import std.exception : enforce; 91 | 92 | bool translate = true; 93 | auto message = Appender!string(); 94 | 95 | foreach (translationUnit; translationUnits) 96 | { 97 | foreach (diagnostics ; translationUnit.diagnostics) 98 | { 99 | auto severity = diagnostics.severity; 100 | 101 | with (CXDiagnosticSeverity) 102 | if (translate) 103 | translate = !(severity == error || severity == fatal); 104 | 105 | message.put(diagnostics.format); 106 | message.put("\n"); 107 | } 108 | } 109 | 110 | enforce!DStepException(translate, message.data); 111 | } 112 | 113 | static string[] makeOutputFiles(Configuration config) 114 | { 115 | import std.algorithm; 116 | import std.array; 117 | import std.range; 118 | 119 | import dstep.driver.Util : makeDefaultOutputFile; 120 | 121 | auto inputFiles = config.inputFiles; 122 | 123 | // when only one input file is supplied, -o argument is 124 | // interpreted as file path, otherwise as base directory path 125 | if (inputFiles.length == 1) 126 | { 127 | return [config.output.empty 128 | ? makeDefaultOutputFile(inputFiles.front, false) 129 | : config.output]; 130 | } 131 | else 132 | { 133 | alias fmap = file => Path.buildPath( 134 | config.output, 135 | makeDefaultOutputFile(file, false)); 136 | 137 | return inputFiles.map!fmap.array; 138 | } 139 | } 140 | 141 | static TranslationUnit[] makeTranslationUnits(Configuration config) 142 | { 143 | Index translationIndex = Index(false, false); 144 | Compiler compiler; 145 | 146 | auto translationUnits = new TranslationUnit[config.inputFiles.length]; 147 | 148 | foreach (index, ref unit; translationUnits) 149 | { 150 | unit = TranslationUnit.parse( 151 | translationIndex, 152 | config.inputFiles[index], 153 | config.clangParams ~ compiler.internalFlags, 154 | compiler.internalHeaders); 155 | } 156 | 157 | return translationUnits; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /tests/support/Assertions.d: -------------------------------------------------------------------------------- 1 | module tests.support.Assertions; 2 | 3 | import core.exception : AssertError; 4 | 5 | import tests.support.DStepRunner; 6 | 7 | struct TestFile 8 | { 9 | string expected; 10 | string actual; 11 | } 12 | 13 | void assertRunsDStepCFile( 14 | string expectedPath, 15 | string cPath, 16 | string[] arguments = [], 17 | bool strict = false, 18 | string file = __FILE__, 19 | size_t line = __LINE__) 20 | { 21 | string[] extended = arguments ~ ["-Iresources"]; 22 | 23 | assertRunsDStep( 24 | [TestFile(expectedPath, cPath)], 25 | extended, 26 | strict, 27 | file, 28 | line 29 | ); 30 | } 31 | 32 | void assertRunsDStepCFiles( 33 | TestFile[] filesPaths, 34 | string[] arguments = [], 35 | bool strict = false, 36 | string file = __FILE__, 37 | size_t line = __LINE__) 38 | { 39 | string[] extended = arguments ~ ["-Iresources"]; 40 | 41 | assertRunsDStep( 42 | filesPaths, 43 | extended, 44 | strict, 45 | file, 46 | line 47 | ); 48 | } 49 | 50 | void assertRunsDStepObjCFile( 51 | string expectedPath, 52 | string objCPath, 53 | string[] arguments = [], 54 | bool strict = false, 55 | string file = __FILE__, 56 | size_t line = __LINE__) 57 | { 58 | string[] extended = arguments ~ ["-ObjC", "-Iresources"]; 59 | 60 | assertRunsDStep( 61 | [TestFile(expectedPath, objCPath)], 62 | extended, 63 | strict, 64 | file, 65 | line 66 | ); 67 | } 68 | 69 | void assertIssuesWarning( 70 | string sourcePath, 71 | string[] arguments = [], 72 | string file = __FILE__, 73 | size_t line = __LINE__) 74 | { 75 | import std.format : format; 76 | import std.algorithm : canFind; 77 | 78 | try 79 | { 80 | auto result = testRunDStep( 81 | [sourcePath], 82 | arguments, 83 | null, 84 | null, 85 | file, 86 | line); 87 | 88 | if (!canFind(result.output, "warning:")) 89 | { 90 | string message = format( 91 | "\nThe output doesn't contain any warnings.\nThe output:\n%s", 92 | result.output); 93 | 94 | throw new AssertError(message, file, line); 95 | } 96 | } 97 | catch (NoGNUStepException) 98 | { 99 | return; 100 | } 101 | } 102 | 103 | void assertRunsDStep( 104 | TestFile[] testFiles, 105 | string[] arguments, 106 | bool strict, 107 | string file = __FILE__, 108 | size_t line = __LINE__) 109 | { 110 | import std.algorithm : map; 111 | import std.array : array; 112 | import std.file : readText, write; 113 | import std.format : format; 114 | import std.traits : ReturnType; 115 | 116 | import tests.support.Util : fileExists, mismatchRegionTranslated; 117 | 118 | auto sep = "----------------"; 119 | 120 | string[] outputContents; 121 | string command; 122 | 123 | ReturnType!testRunDStep result; 124 | 125 | try 126 | { 127 | result = testRunDStep( 128 | testFiles.map!(x => x.actual).array, 129 | arguments, 130 | &outputContents, 131 | &command, 132 | file, 133 | line); 134 | } 135 | catch (NoGNUStepException) 136 | { 137 | return; 138 | } 139 | catch (NoOutputFile exception) 140 | { 141 | auto templ = q"/ 142 | Output file `%4$s` doesn't exist. 143 | %1$s 144 | DStep command: 145 | %2$s 146 | %1$s 147 | DStep output: 148 | %3$s/"; 149 | 150 | auto message = format( 151 | templ, 152 | sep, 153 | command, 154 | exception.result.output, 155 | exception.msg); 156 | 157 | throw new AssertError(message, file, line); 158 | } 159 | 160 | 161 | if (result.status != 0) 162 | { 163 | auto templ = q"/ 164 | DStep failed with status %4$d. 165 | %1$s 166 | DStep command: 167 | %2$s 168 | %1$s 169 | DStep output: 170 | %3$s/"; 171 | 172 | auto message = format( 173 | templ, 174 | sep, 175 | command, 176 | result.output, 177 | result.status); 178 | 179 | throw new AssertError(message, file, line); 180 | } 181 | 182 | foreach (index, testFile; testFiles) 183 | { 184 | if (fileExists(testFile.expected)) 185 | { 186 | string expected = readText(testFile.expected); 187 | string actual = outputContents[index]; 188 | 189 | auto mismatch = mismatchRegionTranslated(actual, expected, 8, strict); 190 | 191 | if (mismatch) 192 | { 193 | auto templ = q"/ 194 | %4$s 195 | %1$s 196 | DStep command: 197 | %2$s 198 | %1$s 199 | DStep output: 200 | %3$s/"; 201 | 202 | string message = format( 203 | templ, 204 | sep, 205 | command, 206 | result.output, 207 | mismatch); 208 | 209 | throw new AssertError(message, file, line); 210 | } 211 | } 212 | else 213 | { 214 | write(testFile.expected, outputContents[index]); 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /clang/c/CXCompilationDatabase.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides a public interface to use CompilationDatabase without *| 11 | |* the full Clang C++ API. *| 12 | |* *| 13 | \*===----------------------------------------------------------------------===*/ 14 | 15 | module clang.c.CXCompilationDatabase; 16 | 17 | public import clang.c.CXString; 18 | 19 | extern (C): 20 | 21 | /** \defgroup COMPILATIONDB CompilationDatabase functions 22 | * \ingroup CINDEX 23 | * 24 | * @{ 25 | */ 26 | 27 | /** 28 | * A compilation database holds all information used to compile files in a 29 | * project. For each file in the database, it can be queried for the working 30 | * directory or the command line used for the compiler invocation. 31 | * 32 | * Must be freed by \c clang_CompilationDatabase_dispose 33 | */ 34 | alias CXCompilationDatabase = void*; 35 | 36 | /** 37 | * Contains the results of a search in the compilation database 38 | * 39 | * When searching for the compile command for a file, the compilation db can 40 | * return several commands, as the file may have been compiled with 41 | * different options in different places of the project. This choice of compile 42 | * commands is wrapped in this opaque data structure. It must be freed by 43 | * \c clang_CompileCommands_dispose. 44 | */ 45 | alias CXCompileCommands = void*; 46 | 47 | /** 48 | * Represents the command line invocation to compile a specific file. 49 | */ 50 | alias CXCompileCommand = void*; 51 | 52 | /** 53 | * Error codes for Compilation Database 54 | */ 55 | enum CXCompilationDatabase_Error 56 | { 57 | /* 58 | * No error occurred 59 | */ 60 | noError = 0, 61 | 62 | /* 63 | * Database can not be loaded 64 | */ 65 | canNotLoadDatabase = 1 66 | } 67 | 68 | /** 69 | * Creates a compilation database from the database found in directory 70 | * buildDir. For example, CMake can output a compile_commands.json which can 71 | * be used to build the database. 72 | * 73 | * It must be freed by \c clang_CompilationDatabase_dispose. 74 | */ 75 | CXCompilationDatabase clang_CompilationDatabase_fromDirectory( 76 | const(char)* BuildDir, 77 | CXCompilationDatabase_Error* ErrorCode); 78 | 79 | /** 80 | * Free the given compilation database 81 | */ 82 | void clang_CompilationDatabase_dispose(CXCompilationDatabase); 83 | 84 | /** 85 | * Find the compile commands used for a file. The compile commands 86 | * must be freed by \c clang_CompileCommands_dispose. 87 | */ 88 | CXCompileCommands clang_CompilationDatabase_getCompileCommands( 89 | CXCompilationDatabase, 90 | const(char)* CompleteFileName); 91 | 92 | /** 93 | * Get all the compile commands in the given compilation database. 94 | */ 95 | CXCompileCommands clang_CompilationDatabase_getAllCompileCommands( 96 | CXCompilationDatabase); 97 | 98 | /** 99 | * Free the given CompileCommands 100 | */ 101 | void clang_CompileCommands_dispose(CXCompileCommands); 102 | 103 | /** 104 | * Get the number of CompileCommand we have for a file 105 | */ 106 | uint clang_CompileCommands_getSize(CXCompileCommands); 107 | 108 | /** 109 | * Get the I'th CompileCommand for a file 110 | * 111 | * Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands) 112 | */ 113 | CXCompileCommand clang_CompileCommands_getCommand(CXCompileCommands, uint I); 114 | 115 | /** 116 | * Get the working directory where the CompileCommand was executed from 117 | */ 118 | CXString clang_CompileCommand_getDirectory(CXCompileCommand); 119 | 120 | /** 121 | * Get the filename associated with the CompileCommand. 122 | */ 123 | CXString clang_CompileCommand_getFilename(CXCompileCommand); 124 | 125 | /** 126 | * Get the number of arguments in the compiler invocation. 127 | * 128 | */ 129 | uint clang_CompileCommand_getNumArgs(CXCompileCommand); 130 | 131 | /** 132 | * Get the I'th argument value in the compiler invocations 133 | * 134 | * Invariant : 135 | * - argument 0 is the compiler executable 136 | */ 137 | CXString clang_CompileCommand_getArg(CXCompileCommand, uint I); 138 | 139 | /** 140 | * Get the number of source mappings for the compiler invocation. 141 | */ 142 | uint clang_CompileCommand_getNumMappedSources(CXCompileCommand); 143 | 144 | /** 145 | * Get the I'th mapped source path for the compiler invocation. 146 | */ 147 | CXString clang_CompileCommand_getMappedSourcePath(CXCompileCommand, uint I); 148 | 149 | /** 150 | * Get the I'th mapped source content for the compiler invocation. 151 | */ 152 | CXString clang_CompileCommand_getMappedSourceContent(CXCompileCommand, uint I); 153 | 154 | /** 155 | * @} 156 | */ 157 | 158 | -------------------------------------------------------------------------------- /clang/c/BuildSystem.d: -------------------------------------------------------------------------------- 1 | /*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides various utilities for use by build systems. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.BuildSystem; 15 | 16 | public import clang.c.CXErrorCode; 17 | 18 | extern (C): 19 | 20 | /** 21 | * \defgroup BUILD_SYSTEM Build system utilities 22 | * @{ 23 | */ 24 | 25 | /** 26 | * Return the timestamp for use with Clang's 27 | * \c -fbuild-session-timestamp= option. 28 | */ 29 | ulong clang_getBuildSessionTimestamp(); 30 | 31 | /** 32 | * Object encapsulating information about overlaying virtual 33 | * file/directories over the real file system. 34 | */ 35 | struct CXVirtualFileOverlayImpl; 36 | alias CXVirtualFileOverlay = CXVirtualFileOverlayImpl*; 37 | 38 | /** 39 | * Create a \c CXVirtualFileOverlay object. 40 | * Must be disposed with \c clang_VirtualFileOverlay_dispose(). 41 | * 42 | * \param options is reserved, always pass 0. 43 | */ 44 | CXVirtualFileOverlay clang_VirtualFileOverlay_create(uint options); 45 | 46 | /** 47 | * Map an absolute virtual file path to an absolute real one. 48 | * The virtual path must be canonicalized (not contain "."/".."). 49 | * \returns 0 for success, non-zero to indicate an error. 50 | */ 51 | CXErrorCode clang_VirtualFileOverlay_addFileMapping( 52 | CXVirtualFileOverlay, 53 | const(char)* virtualPath, 54 | const(char)* realPath); 55 | 56 | /** 57 | * Set the case sensitivity for the \c CXVirtualFileOverlay object. 58 | * The \c CXVirtualFileOverlay object is case-sensitive by default, this 59 | * option can be used to override the default. 60 | * \returns 0 for success, non-zero to indicate an error. 61 | */ 62 | CXErrorCode clang_VirtualFileOverlay_setCaseSensitivity( 63 | CXVirtualFileOverlay, 64 | int caseSensitive); 65 | 66 | /** 67 | * Write out the \c CXVirtualFileOverlay object to a char buffer. 68 | * 69 | * \param options is reserved, always pass 0. 70 | * \param out_buffer_ptr pointer to receive the buffer pointer, which should be 71 | * disposed using \c clang_free(). 72 | * \param out_buffer_size pointer to receive the buffer size. 73 | * \returns 0 for success, non-zero to indicate an error. 74 | */ 75 | CXErrorCode clang_VirtualFileOverlay_writeToBuffer( 76 | CXVirtualFileOverlay, 77 | uint options, 78 | char** out_buffer_ptr, 79 | uint* out_buffer_size); 80 | 81 | /** 82 | * free memory allocated by libclang, such as the buffer returned by 83 | * \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer(). 84 | * 85 | * \param buffer memory pointer to free. 86 | */ 87 | void clang_free(void* buffer); 88 | 89 | /** 90 | * Dispose a \c CXVirtualFileOverlay object. 91 | */ 92 | void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay); 93 | 94 | /** 95 | * Object encapsulating information about a module.map file. 96 | */ 97 | struct CXModuleMapDescriptorImpl; 98 | alias CXModuleMapDescriptor = CXModuleMapDescriptorImpl*; 99 | 100 | /** 101 | * Create a \c CXModuleMapDescriptor object. 102 | * Must be disposed with \c clang_ModuleMapDescriptor_dispose(). 103 | * 104 | * \param options is reserved, always pass 0. 105 | */ 106 | CXModuleMapDescriptor clang_ModuleMapDescriptor_create(uint options); 107 | 108 | /** 109 | * Sets the framework module name that the module.map describes. 110 | * \returns 0 for success, non-zero to indicate an error. 111 | */ 112 | CXErrorCode clang_ModuleMapDescriptor_setFrameworkModuleName( 113 | CXModuleMapDescriptor, 114 | const(char)* name); 115 | 116 | /** 117 | * Sets the umbrella header name that the module.map describes. 118 | * \returns 0 for success, non-zero to indicate an error. 119 | */ 120 | CXErrorCode clang_ModuleMapDescriptor_setUmbrellaHeader( 121 | CXModuleMapDescriptor, 122 | const(char)* name); 123 | 124 | /** 125 | * Write out the \c CXModuleMapDescriptor object to a char buffer. 126 | * 127 | * \param options is reserved, always pass 0. 128 | * \param out_buffer_ptr pointer to receive the buffer pointer, which should be 129 | * disposed using \c clang_free(). 130 | * \param out_buffer_size pointer to receive the buffer size. 131 | * \returns 0 for success, non-zero to indicate an error. 132 | */ 133 | CXErrorCode clang_ModuleMapDescriptor_writeToBuffer( 134 | CXModuleMapDescriptor, 135 | uint options, 136 | char** out_buffer_ptr, 137 | uint* out_buffer_size); 138 | 139 | /** 140 | * Dispose a \c CXModuleMapDescriptor object. 141 | */ 142 | void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor); 143 | 144 | /** 145 | * @} 146 | */ 147 | 148 | /* CLANG_C_BUILD_SYSTEM_H */ 149 | -------------------------------------------------------------------------------- /dstep/translator/ConvertCase.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright: Copyright (c) 2017 Wojciech Szęszoł. All rights reserved. 3 | * Authors: Wojciech Szęszoł 4 | * Version: Initial created: October 02, 2017 5 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 | */ 7 | module dstep.translator.ConvertCase; 8 | 9 | auto splitSpelling(string spelling) 10 | { 11 | import std.algorithm; 12 | import std.ascii; 13 | import std.range; 14 | 15 | struct Range 16 | { 17 | private string spelling; 18 | private string next; 19 | private bool capitals; 20 | 21 | this(string spelling) 22 | { 23 | this.spelling = spelling.stripLeft('_'); 24 | capitals = !spelling.canFind!isLower; 25 | popFront(); 26 | } 27 | 28 | bool empty() const 29 | { 30 | return next.empty; 31 | } 32 | 33 | string front() const 34 | { 35 | return next; 36 | } 37 | 38 | void popFront() 39 | { 40 | if (spelling.empty) 41 | { 42 | next = spelling; 43 | } 44 | else 45 | { 46 | size_t end = capitals 47 | ? spelling[1 .. $].countUntil!(a => a == '_') 48 | : spelling[1 .. $].countUntil!( 49 | a => !a.isLower && !a.isDigit); 50 | 51 | end = end == -1 ? spelling.length : end + 1; 52 | next = spelling[0 .. end]; 53 | spelling = spelling[end .. $].stripLeft('_'); 54 | } 55 | } 56 | } 57 | 58 | return Range(spelling); 59 | } 60 | 61 | unittest 62 | { 63 | import std.array; 64 | 65 | assert(splitSpelling("").array == []); 66 | assert(splitSpelling("__").array == []); 67 | assert(splitSpelling("x").array == ["x"]); 68 | assert(splitSpelling("X").array == ["X"]); 69 | assert(splitSpelling("xxx").array == ["xxx"]); 70 | assert(splitSpelling("xxxXxx").array == ["xxx", "Xxx"]); 71 | assert(splitSpelling("xxxXxxYyy").array == ["xxx", "Xxx", "Yyy"]); 72 | assert(splitSpelling("xxxXxxYYY").array == ["xxx", "Xxx", "Y", "Y", "Y"]); 73 | assert(splitSpelling("xxx_Xxx__YYY").array == ["xxx", "Xxx", "Y", "Y", "Y"]); 74 | assert(splitSpelling("__xxx_Xxx__YYY__").array == ["xxx", "Xxx", "Y", "Y", "Y"]); 75 | assert(splitSpelling("YYY").array == ["YYY"]); 76 | assert(splitSpelling("Y_Y__XXY").array == ["Y", "Y", "XXY"]); 77 | assert(splitSpelling("__Y_Y__XXY__").array == ["Y", "Y", "XXY"]); 78 | 79 | assert(splitSpelling("xyz0").array == ["xyz0"]); 80 | } 81 | 82 | string toCamelCase(string spelling) 83 | { 84 | import std.algorithm; 85 | import std.array; 86 | import std.ascii; 87 | import std.math; 88 | 89 | auto split = spelling.splitSpelling(); 90 | 91 | if (split.empty) 92 | { 93 | return string.init; 94 | } 95 | else 96 | { 97 | char[] camelCase(string x) 98 | { 99 | return (cast(char) x[0].toUpper) ~ 100 | x[1 .. $].map!(x => cast(char) x.toLower).array; 101 | } 102 | 103 | char[] front; 104 | 105 | while (split.front.length == 1) 106 | { 107 | front ~= cast(char) split.front.front.toLower; 108 | split.popFront(); 109 | } 110 | 111 | if (front.empty) 112 | { 113 | front = split.front.map!(x => cast(char) x.toLower).array; 114 | split.popFront(); 115 | } 116 | 117 | return (front ~ split.map!camelCase.join).idup; 118 | } 119 | } 120 | 121 | unittest 122 | { 123 | import std.array; 124 | 125 | assert("".toCamelCase() == ""); 126 | assert("x".toCamelCase() == "x"); 127 | assert("X".toCamelCase() == "x"); 128 | assert("xy".toCamelCase() == "xy"); 129 | assert("xy_zw".toCamelCase() == "xyZw"); 130 | assert("xyZw".toCamelCase() == "xyZw"); 131 | assert("XY_ZW".toCamelCase() == "xyZw"); 132 | assert("XXXy_ZW".toCamelCase() == "xxXyZW"); 133 | assert("XXy_ZW".toCamelCase() == "xXyZW"); 134 | } 135 | 136 | string toSnakeCase(string spelling) 137 | { 138 | import std.algorithm; 139 | import std.range; 140 | import std.uni; 141 | import std.utf; 142 | 143 | auto split = spelling.splitSpelling(); 144 | 145 | if (split.empty) 146 | { 147 | return string.init; 148 | } 149 | else 150 | { 151 | char[] front; 152 | 153 | while (split.front.length == 1) 154 | { 155 | front ~= cast(char) split.front.front.toLower; 156 | split.popFront(); 157 | } 158 | 159 | if (front.empty) 160 | { 161 | front = split.front.dup; 162 | split.popFront(); 163 | } 164 | 165 | return chain(only(front), split).join('_').map!toLower.toUTF8(); 166 | } 167 | } 168 | 169 | unittest 170 | { 171 | import std.array; 172 | 173 | assert("".toSnakeCase() == ""); 174 | assert("x".toSnakeCase() == "x"); 175 | assert("X".toSnakeCase() == "x"); 176 | assert("xy".toSnakeCase() == "xy"); 177 | assert("xy_zw".toSnakeCase() == "xy_zw"); 178 | assert("xyZw".toSnakeCase() == "xy_zw"); 179 | assert("XY_ZW".toSnakeCase() == "xy_zw"); 180 | assert("XXXy_ZW".toSnakeCase() == "xx_xy_z_w"); 181 | assert("XXy_ZW".toSnakeCase() == "x_xy_z_w"); 182 | } 183 | -------------------------------------------------------------------------------- /tests/functional/clang-c/BuildSystem.d: -------------------------------------------------------------------------------- 1 | /*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides various utilities for use by build systems. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | module clang.c.build_system; 15 | 16 | public import clang.c.cx_error_code; 17 | 18 | extern (C): 19 | 20 | /** 21 | * \defgroup BUILD_SYSTEM Build system utilities 22 | * @{ 23 | */ 24 | 25 | /** 26 | * \brief Return the timestamp for use with Clang's 27 | * \c -fbuild-session-timestamp= option. 28 | */ 29 | ulong clang_getBuildSessionTimestamp (); 30 | 31 | /** 32 | * \brief Object encapsulating information about overlaying virtual 33 | * file/directories over the real file system. 34 | */ 35 | struct CXVirtualFileOverlayImpl; 36 | alias CXVirtualFileOverlay = CXVirtualFileOverlayImpl*; 37 | 38 | /** 39 | * \brief Create a \c CXVirtualFileOverlay object. 40 | * Must be disposed with \c clang_VirtualFileOverlay_dispose(). 41 | * 42 | * \param options is reserved, always pass 0. 43 | */ 44 | CXVirtualFileOverlay clang_VirtualFileOverlay_create (uint options); 45 | 46 | /** 47 | * \brief Map an absolute virtual file path to an absolute real one. 48 | * The virtual path must be canonicalized (not contain "."/".."). 49 | * \returns 0 for success, non-zero to indicate an error. 50 | */ 51 | CXErrorCode clang_VirtualFileOverlay_addFileMapping ( 52 | CXVirtualFileOverlay, 53 | const(char)* virtualPath, 54 | const(char)* realPath); 55 | 56 | /** 57 | * \brief Set the case sensitivity for the \c CXVirtualFileOverlay object. 58 | * The \c CXVirtualFileOverlay object is case-sensitive by default, this 59 | * option can be used to override the default. 60 | * \returns 0 for success, non-zero to indicate an error. 61 | */ 62 | CXErrorCode clang_VirtualFileOverlay_setCaseSensitivity ( 63 | CXVirtualFileOverlay, 64 | int caseSensitive); 65 | 66 | /** 67 | * \brief Write out the \c CXVirtualFileOverlay object to a char buffer. 68 | * 69 | * \param options is reserved, always pass 0. 70 | * \param out_buffer_ptr pointer to receive the buffer pointer, which should be 71 | * disposed using \c clang_free(). 72 | * \param out_buffer_size pointer to receive the buffer size. 73 | * \returns 0 for success, non-zero to indicate an error. 74 | */ 75 | CXErrorCode clang_VirtualFileOverlay_writeToBuffer ( 76 | CXVirtualFileOverlay, 77 | uint options, 78 | char** out_buffer_ptr, 79 | uint* out_buffer_size); 80 | 81 | /** 82 | * \brief free memory allocated by libclang, such as the buffer returned by 83 | * \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer(). 84 | * 85 | * \param buffer memory pointer to free. 86 | */ 87 | void clang_free (void* buffer); 88 | 89 | /** 90 | * \brief Dispose a \c CXVirtualFileOverlay object. 91 | */ 92 | void clang_VirtualFileOverlay_dispose (CXVirtualFileOverlay); 93 | 94 | /** 95 | * \brief Object encapsulating information about a module.map file. 96 | */ 97 | struct CXModuleMapDescriptorImpl; 98 | alias CXModuleMapDescriptor = CXModuleMapDescriptorImpl*; 99 | 100 | /** 101 | * \brief Create a \c CXModuleMapDescriptor object. 102 | * Must be disposed with \c clang_ModuleMapDescriptor_dispose(). 103 | * 104 | * \param options is reserved, always pass 0. 105 | */ 106 | CXModuleMapDescriptor clang_ModuleMapDescriptor_create (uint options); 107 | 108 | /** 109 | * \brief Sets the framework module name that the module.map describes. 110 | * \returns 0 for success, non-zero to indicate an error. 111 | */ 112 | CXErrorCode clang_ModuleMapDescriptor_setFrameworkModuleName ( 113 | CXModuleMapDescriptor, 114 | const(char)* name); 115 | 116 | /** 117 | * \brief Sets the umbrealla header name that the module.map describes. 118 | * \returns 0 for success, non-zero to indicate an error. 119 | */ 120 | CXErrorCode clang_ModuleMapDescriptor_setUmbrellaHeader ( 121 | CXModuleMapDescriptor, 122 | const(char)* name); 123 | 124 | /** 125 | * \brief Write out the \c CXModuleMapDescriptor object to a char buffer. 126 | * 127 | * \param options is reserved, always pass 0. 128 | * \param out_buffer_ptr pointer to receive the buffer pointer, which should be 129 | * disposed using \c clang_free(). 130 | * \param out_buffer_size pointer to receive the buffer size. 131 | * \returns 0 for success, non-zero to indicate an error. 132 | */ 133 | CXErrorCode clang_ModuleMapDescriptor_writeToBuffer ( 134 | CXModuleMapDescriptor, 135 | uint options, 136 | char** out_buffer_ptr, 137 | uint* out_buffer_size); 138 | 139 | /** 140 | * \brief Dispose a \c CXModuleMapDescriptor object. 141 | */ 142 | void clang_ModuleMapDescriptor_dispose (CXModuleMapDescriptor); 143 | 144 | /** 145 | * @} 146 | */ 147 | 148 | /* CLANG_C_BUILD_SYSTEM_H */ 149 | -------------------------------------------------------------------------------- /tests/functional/clang-c/CXCompilationDatabase.d: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\ 2 | |* *| 3 | |* The LLVM Compiler Infrastructure *| 4 | |* *| 5 | |* This file is distributed under the University of Illinois Open Source *| 6 | |* License. See LICENSE.TXT for details. *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides a public inferface to use CompilationDatabase without *| 11 | |* the full Clang C++ API. *| 12 | |* *| 13 | \*===----------------------------------------------------------------------===*/ 14 | 15 | module clang.c.cx_compilation_database; 16 | 17 | public import clang.c.cx_string; 18 | 19 | extern (C): 20 | 21 | /** \defgroup COMPILATIONDB CompilationDatabase functions 22 | * \ingroup CINDEX 23 | * 24 | * @{ 25 | */ 26 | 27 | /** 28 | * A compilation database holds all information used to compile files in a 29 | * project. For each file in the database, it can be queried for the working 30 | * directory or the command line used for the compiler invocation. 31 | * 32 | * Must be freed by \c clang_CompilationDatabase_dispose 33 | */ 34 | alias CXCompilationDatabase = void*; 35 | 36 | /** 37 | * \brief Contains the results of a search in the compilation database 38 | * 39 | * When searching for the compile command for a file, the compilation db can 40 | * return several commands, as the file may have been compiled with 41 | * different options in different places of the project. This choice of compile 42 | * commands is wrapped in this opaque data structure. It must be freed by 43 | * \c clang_CompileCommands_dispose. 44 | */ 45 | alias CXCompileCommands = void*; 46 | 47 | /** 48 | * \brief Represents the command line invocation to compile a specific file. 49 | */ 50 | alias CXCompileCommand = void*; 51 | 52 | /** 53 | * \brief Error codes for Compilation Database 54 | */ 55 | enum CXCompilationDatabase_Error 56 | { 57 | /* 58 | * \brief No error occurred 59 | */ 60 | CXCompilationDatabase_NoError = 0, 61 | 62 | /* 63 | * \brief Database can not be loaded 64 | */ 65 | CXCompilationDatabase_CanNotLoadDatabase = 1 66 | } 67 | 68 | /** 69 | * \brief Creates a compilation database from the database found in directory 70 | * buildDir. For example, CMake can output a compile_commands.json which can 71 | * be used to build the database. 72 | * 73 | * It must be freed by \c clang_CompilationDatabase_dispose. 74 | */ 75 | CXCompilationDatabase clang_CompilationDatabase_fromDirectory ( 76 | const(char)* BuildDir, 77 | CXCompilationDatabase_Error* ErrorCode); 78 | 79 | /** 80 | * \brief Free the given compilation database 81 | */ 82 | void clang_CompilationDatabase_dispose (CXCompilationDatabase); 83 | 84 | /** 85 | * \brief Find the compile commands used for a file. The compile commands 86 | * must be freed by \c clang_CompileCommands_dispose. 87 | */ 88 | CXCompileCommands clang_CompilationDatabase_getCompileCommands ( 89 | CXCompilationDatabase, 90 | const(char)* CompleteFileName); 91 | 92 | /** 93 | * \brief Get all the compile commands in the given compilation database. 94 | */ 95 | CXCompileCommands clang_CompilationDatabase_getAllCompileCommands ( 96 | CXCompilationDatabase); 97 | 98 | /** 99 | * \brief Free the given CompileCommands 100 | */ 101 | void clang_CompileCommands_dispose (CXCompileCommands); 102 | 103 | /** 104 | * \brief Get the number of CompileCommand we have for a file 105 | */ 106 | uint clang_CompileCommands_getSize (CXCompileCommands); 107 | 108 | /** 109 | * \brief Get the I'th CompileCommand for a file 110 | * 111 | * Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands) 112 | */ 113 | CXCompileCommand clang_CompileCommands_getCommand (CXCompileCommands, uint I); 114 | 115 | /** 116 | * \brief Get the working directory where the CompileCommand was executed from 117 | */ 118 | CXString clang_CompileCommand_getDirectory (CXCompileCommand); 119 | 120 | /** 121 | * \brief Get the filename associated with the CompileCommand. 122 | */ 123 | CXString clang_CompileCommand_getFilename (CXCompileCommand); 124 | 125 | /** 126 | * \brief Get the number of arguments in the compiler invocation. 127 | * 128 | */ 129 | uint clang_CompileCommand_getNumArgs (CXCompileCommand); 130 | 131 | /** 132 | * \brief Get the I'th argument value in the compiler invocations 133 | * 134 | * Invariant : 135 | * - argument 0 is the compiler executable 136 | */ 137 | CXString clang_CompileCommand_getArg (CXCompileCommand, uint I); 138 | 139 | /** 140 | * \brief Get the number of source mappings for the compiler invocation. 141 | */ 142 | uint clang_CompileCommand_getNumMappedSources (CXCompileCommand); 143 | 144 | /** 145 | * \brief Get the I'th mapped source path for the compiler invocation. 146 | */ 147 | CXString clang_CompileCommand_getMappedSourcePath (CXCompileCommand, uint I); 148 | 149 | /** 150 | * \brief Get the I'th mapped source content for the compiler invocation. 151 | */ 152 | CXString clang_CompileCommand_getMappedSourceContent (CXCompileCommand, uint I); 153 | 154 | /** 155 | * @} 156 | */ 157 | 158 | --------------------------------------------------------------------------------