diff options
-rw-r--r-- | ccode/valaccodefunction.vala | 15 | ||||
-rw-r--r-- | ccode/valaccodefunctiondeclarator.vala | 15 | ||||
-rw-r--r-- | ccode/valaccodemodifiers.vala | 4 | ||||
-rw-r--r-- | codegen/valaccodemethodmodule.vala | 12 | ||||
-rw-r--r-- | codegen/valagtypemodule.vala | 6 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/methods/bug710862.vala | 76 | ||||
-rw-r--r-- | vapi/glib-2.0.vapi | 2 |
8 files changed, 127 insertions, 4 deletions
diff --git a/ccode/valaccodefunction.vala b/ccode/valaccodefunction.vala index cd3e385d0..394fdac2b 100644 --- a/ccode/valaccodefunction.vala +++ b/ccode/valaccodefunction.vala @@ -118,8 +118,10 @@ public class Vala.CCodeFunction : CCodeNode { writer.write_string (name); writer.write_string (" ("); + bool has_args = (CCodeModifiers.PRINTF in modifiers || CCodeModifiers.SCANF in modifiers); int i = 0; int format_arg_index = -1; + int args_index = -1; foreach (CCodeParameter param in parameters) { if (i > 0) { writer.write_string (", "); @@ -128,6 +130,11 @@ public class Vala.CCodeFunction : CCodeNode { if (CCodeModifiers.FORMAT_ARG in param.modifiers) { format_arg_index = i; } + if (has_args && param.ellipsis) { + args_index = i; + } else if (has_args && param.type_name == "va_list" && format_arg_index < 0) { + format_arg_index = i - 1; + } i++; } if (i == 0) { @@ -141,7 +148,13 @@ public class Vala.CCodeFunction : CCodeNode { } if (is_declaration) { - if (format_arg_index >= 0) { + if (CCodeModifiers.PRINTF in modifiers) { + format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); + writer.write_string (" G_GNUC_PRINTF(%d,%d)".printf (format_arg_index, args_index + 1)); + } else if (CCodeModifiers.SCANF in modifiers) { + format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); + writer.write_string (" G_GNUC_SCANF(%d,%d)".printf (format_arg_index, args_index + 1)); + } else if (format_arg_index >= 0) { writer.write_string (" G_GNUC_FORMAT(%d)".printf (format_arg_index + 1)); } diff --git a/ccode/valaccodefunctiondeclarator.vala b/ccode/valaccodefunctiondeclarator.vala index 1378662c5..b195f5ae3 100644 --- a/ccode/valaccodefunctiondeclarator.vala +++ b/ccode/valaccodefunctiondeclarator.vala @@ -55,8 +55,10 @@ public class Vala.CCodeFunctionDeclarator : CCodeDeclarator { writer.write_string (name); writer.write_string (") ("); + bool has_args = (CCodeModifiers.PRINTF in modifiers || CCodeModifiers.SCANF in modifiers); int i = 0; int format_arg_index = -1; + int args_index = -1; foreach (CCodeParameter param in parameters) { if (i > 0) { writer.write_string (", "); @@ -65,12 +67,23 @@ public class Vala.CCodeFunctionDeclarator : CCodeDeclarator { if (CCodeModifiers.FORMAT_ARG in param.modifiers) { format_arg_index = i; } + if (has_args && param.ellipsis) { + args_index = i; + } else if (has_args && param.type_name == "va_list" && format_arg_index < 0) { + format_arg_index = i - 1; + } i++; } writer.write_string (")"); - if (format_arg_index >= 0) { + if (CCodeModifiers.PRINTF in modifiers) { + format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); + writer.write_string (" G_GNUC_PRINTF(%d,%d)".printf (format_arg_index, args_index + 1)); + } else if (CCodeModifiers.SCANF in modifiers) { + format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); + writer.write_string (" G_GNUC_SCANF(%d,%d)".printf (format_arg_index, args_index + 1)); + } else if (format_arg_index >= 0) { writer.write_string (" G_GNUC_FORMAT(%d)".printf (format_arg_index + 1)); } } diff --git a/ccode/valaccodemodifiers.vala b/ccode/valaccodemodifiers.vala index 75c5a99d7..257423040 100644 --- a/ccode/valaccodemodifiers.vala +++ b/ccode/valaccodemodifiers.vala @@ -39,5 +39,7 @@ public enum Vala.CCodeModifiers { UNUSED = 1 << 9, CONSTRUCTOR = 1 << 10, DESTRUCTOR = 1 << 11, - FORMAT_ARG = 1 << 12 + FORMAT_ARG = 1 << 12, + PRINTF = 1 << 13, + SCANF = 1 << 14 } diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index ce127f59a..8e4c213b9 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -1022,6 +1022,12 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { } last_pos = min_pos; } + + if (m.printf_format) { + func.modifiers |= CCodeModifiers.PRINTF; + } else if (m.scanf_format) { + func.modifiers |= CCodeModifiers.SCANF; + } } public void generate_vfunc (Method m, DataType return_type, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression> carg_map, string suffix = "", int direction = 3) { @@ -1091,6 +1097,12 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { } } + if (m.printf_format) { + vfunc.modifiers |= CCodeModifiers.PRINTF; + } else if (m.scanf_format) { + vfunc.modifiers |= CCodeModifiers.SCANF; + } + cfile.add_function (vfunc); pop_context (); diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala index a9073e31a..1b5c2f141 100644 --- a/codegen/valagtypemodule.vala +++ b/codegen/valagtypemodule.vala @@ -387,6 +387,12 @@ public class Vala.GTypeModule : GErrorModule { var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m)); var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal); + if (m.printf_format) { + vdeclarator.modifiers |= CCodeModifiers.PRINTF; + } else if (m.scanf_format) { + vdeclarator.modifiers |= CCodeModifiers.SCANF; + } + generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator); var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type)); diff --git a/tests/Makefile.am b/tests/Makefile.am index d3c709a6b..abd60f0fc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -69,6 +69,7 @@ TESTS = \ methods/bug653391.vala \ methods/bug653908.vala \ methods/bug663210.vala \ + methods/bug710862.vala \ methods/bug723009.vala \ methods/bug723195.vala \ methods/bug726347.vala \ diff --git a/tests/methods/bug710862.vala b/tests/methods/bug710862.vala new file mode 100644 index 000000000..856d110ad --- /dev/null +++ b/tests/methods/bug710862.vala @@ -0,0 +1,76 @@ +class Foo : Object { + [PrintfFormat] + public void print (string format, ...) { + var vargs = va_list (); + print_vargs (format, vargs); + } + + [PrintfFormat] + public void print_shift ([FormatArg] string format, int shift, ...) { + var vargs = va_list (); + print_shift_vargs (format, shift, vargs); + } + + [PrintfFormat] + public void print_vargs (string format, va_list vargs) { + } + + [PrintfFormat] + public void print_shift_vargs ([FormatArg] string format, int shift, va_list vargs) { + } + + [NoWrapper] + [PrintfFormat] + public virtual void print_vfunc_vargs (string format, va_list vargs) { + } + + [NoWrapper] + [PrintfFormat] + public virtual void print_vfunc_shift_vargs ([FormatArg] string format, int shift, va_list vargs) { + } + + [ScanfFormat] + public void scan (string input, string format, ...) { + } + + [NoWrapper] + [ScanfFormat] + public virtual void scan_vfunc_vargs (string input, string format, va_list vargs) { + } +} + +[PrintfFormat] +void print_something (string format, ...) { + var vargs = va_list (); + print_something_vargs (format, vargs); +} + +[PrintfFormat] +void print_something_shift ([FormatArg] string format, int shift, ...) { + var vargs = va_list (); + print_something_vargs (format, vargs); +} + +[PrintfFormat] +void print_something_vargs (string format, va_list vargs) { +} + +[PrintfFormat] +void print_something_shift_vargs ([FormatArg] string format, int shift, va_list vargs) { +} + +[ScanfFormat] +void scan_something (string input, string format, ...) { +} + +void main () { + int i; + + print_something ("%d", 42); + print_something_shift ("%d", 0, 42); + scan_something ("42", "%d", out i); + + var foo = new Foo (); + foo.print ("%d", 42); + foo.scan ("42", "%d", out i); +} diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index 3e50146d4..db96e28db 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -1051,7 +1051,7 @@ public class string { [CCode (cname = "g_strdup_vprintf")] public string vprintf (va_list args); [CCode (cname = "sscanf", cheader_filename = "stdio.h"), ScanfFormat] - public int scanf (...); + public int scanf (string format, ...); [CCode (cname = "g_strconcat")] public string concat (string string2, ...); [CCode (cname = "g_strescape")] |