]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add G_GNUC_PRINTF/SCANF attribute for Printf/ScanfFormat functions
authorRico Tzschichholz <ricotz@ubuntu.com>
Tue, 8 Nov 2016 15:37:31 +0000 (16:37 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 9 Nov 2016 14:56:01 +0000 (15:56 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=710862

ccode/valaccodefunction.vala
ccode/valaccodefunctiondeclarator.vala
ccode/valaccodemodifiers.vala
codegen/valaccodemethodmodule.vala
codegen/valagtypemodule.vala
tests/Makefile.am
tests/methods/bug710862.vala [new file with mode: 0644]
vapi/glib-2.0.vapi

index cd3e385d0f3ebaa853488075c1c2805813492056..394fdac2b1de0ebd91102a2324a9ff829c925f14 100644 (file)
@@ -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));
                        }
 
index 1378662c51cad689021519dd4c1f98110ac4ad22..b195f5ae38d33cb2ed61f81c0cdddef225e23adc 100644 (file)
@@ -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));
                }
        }
index 75c5a99d756a43fad49f9be4c34014b3be2d001f..2574230407923a5035bbb61d9270fe6ae8be38db 100644 (file)
@@ -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
 }
index ce127f59a6ad51ac81436afbd72518ecdd33019c..8e4c213b9c5a942a774894d36f7fb6b34e89446d 100644 (file)
@@ -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 ();
index a9073e31aaa632721f333804302cd4d62dd0aaf5..1b5c2f1412f2aa844702901e1963a1edfadd0b91 100644 (file)
@@ -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));
index d3c709a6b281f6bb1c940a784fcbe47107d5d860..abd60f0fc60f496f1103505fb165e16b91e41719 100644 (file)
@@ -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 (file)
index 0000000..856d110
--- /dev/null
@@ -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);
+}
index 3e50146d4fec803101af3ba1c7c38db0fea8d99a..db96e28db3506d0706708fe3cc01b080e37c3a49 100644 (file)
@@ -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")]