Commit 6d250808 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

Check printf arguments, fixes bug 483104

2008-06-13  Jürg Billeter  <j@bitron.ch>

	* vala/valasemanticanalyzer.vala:

	Check printf arguments, fixes bug 483104

	* vala/valainterfacewriter.vala:
	* tests/test-034.vala:

	Fix printf arguments

svn path=/trunk/; revision=1578
parent fc4ad72a
2008-06-13 Jürg Billeter <j@bitron.ch>
* vala/valasemanticanalyzer.vala:
Check printf arguments, fixes bug 483104
* vala/valainterfacewriter.vala:
* tests/test-034.vala:
Fix printf arguments
2008-06-13 Jürg Billeter <j@bitron.ch>
* gobject/valaccodegenerator.vala:
......
......@@ -15,14 +15,14 @@ class Maman.Bar : Object {
var b = new B ();
var c = new C ();
stdout.printf ("init: %d %d %d\n", null != a, null != b, null != c);
stdout.printf ("init: %d %d %d\n", null != a ? 1 : 0, null != b ? 1 : 0, null != c ? 1 : 0);
stdout.printf ("is A: %d %d %d\n", a is A, b is A, c is A);
stdout.printf ("is B: %d %d %d\n", a is B, b is B, c is B);
stdout.printf ("is C: %d %d %d\n", a is C, b is C, c is C);
stdout.printf ("is A: %d %d %d\n", (a is A) ? 1 : 0, (b is A) ? 1 : 0, (c is A) ? 1 : 0);
stdout.printf ("is B: %d %d %d\n", (a is B) ? 1 : 0, (b is B) ? 1 : 0, (c is B) ? 1 : 0);
stdout.printf ("is C: %d %d %d\n", (a is C) ? 1 : 0, (b is C) ? 1 : 0, (c is C) ? 1 : 0);
stdout.printf ("as A: %d %d %d\n", null != (a as A), null != (b as A), null != (c as A));
stdout.printf ("as B: %d %d %d\n", null != (a as B), null != (b as B), null != (c as B));
stdout.printf ("as C: %d %d %d\n", null != (a as C), null != (b as C), null != (c as C));
stdout.printf ("as A: %d %d %d\n", null != (a as A) ? 1 : 0, null != (b as A) ? 1 : 0, null != (c as A) ? 1 : 0);
stdout.printf ("as B: %d %d %d\n", null != (a as B) ? 1 : 0, null != (b as B) ? 1 : 0, null != (c as B) ? 1 : 0);
stdout.printf ("as C: %d %d %d\n", null != (a as C) ? 1 : 0, null != (b as C) ? 1 : 0, null != (c as C) ? 1 : 0);
}
}
......@@ -366,7 +366,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
write_string ("[CCode (cprefix = \"%s\", ".printf (en.get_cprefix ()));
if (!en.has_type_id) {
write_string ("has_type_id = \"%d\", ".printf (en.has_type_id));
write_string ("has_type_id = \"%d\", ".printf (en.has_type_id ? 1 : 0));
}
write_string ("cheader_filename = \"%s\")]".printf (cheaders));
......
......@@ -41,11 +41,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
DataType bool_type;
DataType string_type;
DataType uchar_type;
DataType short_type;
DataType ushort_type;
DataType int_type;
DataType uint_type;
DataType long_type;
DataType ulong_type;
DataType size_t_type;
DataType ssize_t_type;
DataType int8_type;
DataType unichar_type;
DataType double_type;
DataType type_type;
Class object_type;
TypeSymbol initially_unowned_type;
......@@ -79,11 +86,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
bool_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("bool"));
string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
uchar_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uchar"));
short_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("short"));
ushort_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ushort"));
int_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int"));
uint_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint"));
long_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("long"));
ulong_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ulong"));
size_t_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("size_t"));
ssize_t_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ssize_t"));
int8_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int8"));
unichar_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("unichar"));
double_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("double"));
// TODO: don't require GLib namespace in semantic analyzer
var glib_ns = root_symbol.scope.lookup ("GLib");
......@@ -1909,6 +1923,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return;
}
Expression last_arg = null;
var args = expr.get_argument_list ();
Iterator<Expression> arg_it = args.iterator ();
foreach (FormalParameter param in params) {
......@@ -1930,6 +1946,142 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
assert (arg.target_type != null);
}
}
last_arg = arg;
}
}
// printf arguments
if (mtype is MethodType && ((MethodType) mtype).method_symbol.printf_format) {
StringLiteral format_literal = null;
if (last_arg != null) {
// use last argument as format string
format_literal = last_arg as StringLiteral;
} else {
// use instance as format string for string.printf (...)
var ma = expr.call as MemberAccess;
if (ma != null) {
format_literal = ma.inner as StringLiteral;
}
}
if (format_literal != null) {
string format = format_literal.eval ();
bool unsupported_format = false;
weak string format_it = format;
unichar c = format_it.get_char ();
while (c != '\0') {
if (c != '%') {
format_it = format_it.next_char ();
c = format_it.get_char ();
continue;
}
format_it = format_it.next_char ();
c = format_it.get_char ();
// flags
while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
format_it = format_it.next_char ();
c = format_it.get_char ();
}
// field width
while (c >= '0' && c <= '9') {
format_it = format_it.next_char ();
c = format_it.get_char ();
}
// precision
if (c == '.') {
format_it = format_it.next_char ();
c = format_it.get_char ();
while (c >= '0' && c <= '9') {
format_it = format_it.next_char ();
c = format_it.get_char ();
}
}
// length modifier
int length = 0;
if (c == 'h') {
length = -1;
format_it = format_it.next_char ();
c = format_it.get_char ();
if (c == 'h') {
length = -2;
format_it = format_it.next_char ();
c = format_it.get_char ();
}
} else if (c == 'l') {
length = 1;
format_it = format_it.next_char ();
c = format_it.get_char ();
} else if (c == 'z') {
length = 2;
format_it = format_it.next_char ();
c = format_it.get_char ();
}
// conversion specifier
DataType param_type = null;
if (c == 'd' || c == 'i' || c == 'c') {
// integer
if (length == -2) {
param_type = int8_type;
} else if (length == -1) {
param_type = short_type;
} else if (length == 0) {
param_type = int_type;
} else if (length == 1) {
param_type = long_type;
} else if (length == 2) {
param_type = ssize_t_type;
}
} else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
// unsigned integer
if (length == -2) {
param_type = uchar_type;
} else if (length == -1) {
param_type = ushort_type;
} else if (length == 0) {
param_type = uint_type;
} else if (length == 1) {
param_type = ulong_type;
} else if (length == 2) {
param_type = size_t_type;
}
} else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
|| c == 'g' || c == 'G' || c == 'a' || c == 'A') {
// double
param_type = double_type;
} else if (c == 's') {
// string
param_type = string_type;
} else if (c == 'p') {
// pointer
param_type = new PointerType (new VoidType ());
} else if (c == '%') {
// literal %
} else {
unsupported_format = true;
break;
}
if (c != '\0') {
format_it = format_it.next_char ();
c = format_it.get_char ();
}
if (param_type != null) {
if (arg_it.next ()) {
Expression arg = arg_it.get ();
arg.target_type = param_type;
} else {
Report.error (expr.source_reference, "Too few arguments for specified format");
return;
}
}
}
if (!unsupported_format && arg_it.next ()) {
Report.error (expr.source_reference, "Too many arguments for specified format");
return;
}
}
}
......@@ -2118,6 +2270,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
Report.error (expr.source_reference, "Invalid type for argument %d".printf (i + 1));
return false;
}
} else if (arg.target_type != null && !arg.value_type.compatible (arg.target_type)) {
// target_type known for printf arguments
expr.error = true;
Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.value_type.to_string (), arg.target_type.to_string ()));
return false;
}
i++;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment