]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support [FormatArg] attribute for parameters
authorJürg Billeter <j@bitron.ch>
Tue, 1 Nov 2016 16:48:15 +0000 (17:48 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Thu, 3 Nov 2016 19:47:31 +0000 (20:47 +0100)
This attribute specifies that the method takes and returns a printf
or scanf format string without modifying the order or types of expected
arguments, e.g., to translate the format string. This allows the
compiler to check the printf/scanf arguments.

vala/valamethod.vala
vala/valamethodcall.vala
vala/valaobjectcreationexpression.vala
vala/valaparameter.vala
vala/valastringliteral.vala
vala/valausedattr.vala

index f0f19809fecf04db190159a45a46d576fef92dd7..4c7b700cc79691bd0f2fd202c86d25f9c16e3de1 100644 (file)
@@ -1047,6 +1047,15 @@ public class Vala.Method : Subroutine, Callable {
                        get_captured_variables ((Collection<LocalVariable>) collection);
                }
        }
+
+       public int get_format_arg_index () {
+               for (int i = 0; i < parameters.size; i++) {
+                       if (parameters[i].format_arg) {
+                               return i;
+                       }
+               }
+               return -1;
+       }
 }
 
 // vim:sw=8 noet
index e604afe34cb8ea3347a6d2226899ee6840446353..7bf0e49c3b5a526d0491fd2fc58c96f850d49b13 100644 (file)
@@ -434,7 +434,7 @@ public class Vala.MethodCall : Expression {
                        StringLiteral format_literal = null;
                        if (last_arg != null) {
                                // use last argument as format string
-                               format_literal = last_arg as StringLiteral;
+                               format_literal = StringLiteral.get_format_literal (last_arg);
                                if (format_literal == null && args.size == params.size - 1) {
                                        // insert "%s" to avoid issues with embedded %
                                        format_literal = new StringLiteral ("\"%s\"");
@@ -454,7 +454,7 @@ public class Vala.MethodCall : Expression {
                                // use instance as format string for string.printf (...)
                                var ma = call as MemberAccess;
                                if (ma != null) {
-                                       format_literal = ma.inner as StringLiteral;
+                                       format_literal = StringLiteral.get_format_literal (ma.inner);
                                }
                        }
                        if (format_literal != null) {
@@ -722,4 +722,16 @@ public class Vala.MethodCall : Expression {
                        arg.get_used_variables (collection);
                }
        }
+
+       public StringLiteral? get_format_literal () {
+               var mtype = this.call.value_type as MethodType;
+               if (mtype != null) {
+                       int format_arg = mtype.method_symbol.get_format_arg_index ();
+                       if (format_arg >= 0 && format_arg < argument_list.size) {
+                               return StringLiteral.get_format_literal (argument_list[format_arg]);
+                       }
+               }
+
+               return null;
+       }
 }
index 5a271b78328efc7b182c63506b5689579a5fa68b..c4b119a44ca03ae9912df09fe975434b7fb9a1bd 100644 (file)
@@ -388,7 +388,7 @@ public class Vala.ObjectCreationExpression : Expression {
                                StringLiteral format_literal = null;
                                if (last_arg != null) {
                                        // use last argument as format string
-                                       format_literal = last_arg as StringLiteral;
+                                       format_literal = StringLiteral.get_format_literal (last_arg);
                                        if (format_literal == null && args.size == m.get_parameters ().size - 1) {
                                                // insert "%s" to avoid issues with embedded %
                                                format_literal = new StringLiteral ("\"%s\"");
@@ -457,7 +457,7 @@ public class Vala.ObjectCreationExpression : Expression {
                                        Report.error (source_reference, "Invalid type for argument 1");
                                }
 
-                               var format_literal = ex as StringLiteral;
+                               var format_literal = StringLiteral.get_format_literal (ex);
                                if (format_literal != null) {
                                        var format = format_literal.eval ();
                                        if (!context.analyzer.check_print_format (format, arg_it, source_reference)) {
index 67d172ebc43d5c4cbde0d4bca3b90c79a286b434..39820718ceb3a75c2b1c59efd930790a029df4ca 100644 (file)
@@ -44,6 +44,12 @@ public class Vala.Parameter : Variable {
        
        public bool captured { get; set; }
 
+       public bool format_arg {
+               get {
+                       return get_attribute ("FormatArg") != null;
+               }
+       }
+
        /**
         * The base parameter of this parameter relative to the base method.
         */
index e54a9c424ddd0206c61581c8f0d79fde14e2a8bc..72970c6d7d51459297c1ebf3c0d210cc54b1c703 100644 (file)
@@ -96,4 +96,18 @@ public class Vala.StringLiteral : Literal {
 
                codegen.visit_expression (this);
        }
+
+       public static StringLiteral? get_format_literal (Expression expr) {
+               var format_literal = expr as StringLiteral;
+               if (format_literal != null) {
+                       return format_literal;
+               }
+
+               var call = expr as MethodCall;
+               if (call != null) {
+                       return call.get_format_literal ();
+               }
+
+               return null;
+       }
 }
index 14fe1d20be29579991072770bf7a4c8aa2358869..2e5840d556ca730ad81ca0d1c9fd93330d046ee3 100644 (file)
@@ -68,6 +68,7 @@ public class Vala.UsedAttr : CodeVisitor {
                "SimpleType", "",
                "PrintfFormat", "",
                "ScanfFormat", "",
+               "FormatArg", "",
 
                "GtkChild", "name", "internal", "",
                "GtkTemplate", "ui", "",