1 module contract.functions; 2 3 4 import contract; 5 import std.array: array; 6 7 8 // See #43 9 @Tags("contract") 10 @("functionproto.deref") 11 @safe unittest { 12 13 const tu = parse( 14 C( 15 q{ 16 int binOp(int (f)(int x, int y), int a, int b); 17 } 18 ) 19 ); 20 21 tu.children.length.should == 1; 22 23 const binOp = tu.child(0); 24 binOp.shouldMatch(Cursor.Kind.FunctionDecl, "binOp"); 25 26 binOp.type.paramTypes.array.length.should == 3; 27 const f = binOp.type.paramTypes.array[0]; 28 // need canonical for old versions of libclang 29 f.canonical.shouldMatch(Type.Kind.FunctionProto, "int (int, int)"); 30 writelnUt(f.pointee); 31 // presumably, not a pointer 32 f.pointee.isInvalid.should == true; 33 } 34 35 36 @Tags("contract") 37 @("functionproto.star") 38 @safe unittest { 39 40 const tu = parse( 41 C( 42 q{ 43 int binOp(int (*f)(int x, int y), int a, int b); 44 } 45 ) 46 ); 47 48 tu.children.length.should == 1; 49 50 const binOp = tu.child(0); 51 binOp.shouldMatch(Cursor.Kind.FunctionDecl, "binOp"); 52 53 binOp.type.paramTypes.array.length.should == 3; 54 const f = binOp.type.paramTypes.array[0]; 55 // Even though the declaration here is effectively the same as the 56 // one in the test above, it shows up as a pointer 57 f.shouldMatch(Type.Kind.Pointer, "int (*)(int, int)"); 58 writelnUt(f.pointee); 59 // it's a pointer 60 f.pointee.isInvalid.should == false; 61 62 f.pointee.canonical.shouldMatch(Type.Kind.FunctionProto, "int (int, int)"); 63 } 64 65 66 @Tags("contract") 67 @("typeof") 68 @safe unittest { 69 70 const tu = parse( 71 C( 72 q{ 73 struct Foo; 74 // typeof is a gcc and clang language extension 75 typeof(struct Foo *) func(); 76 } 77 ) 78 ); 79 80 tu.children.length.should == 2; 81 82 const func = tu.child(1); 83 func.shouldMatch(Cursor.Kind.FunctionDecl, "func"); 84 printChildren(func); 85 func.children.length.should == 1; 86 87 func.returnType.shouldMatch(Type.Kind.Unexposed, "typeof(struct Foo *)"); 88 func.returnType.canonical.shouldMatch(Type.Kind.Pointer, "struct Foo *"); 89 func.returnType.canonical.pointee.shouldMatch(Type.Kind.Record, "struct Foo"); 90 }