summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2017-10-24 07:55:59 +0200
committerBenjamin Otte <otte@redhat.com>2017-10-30 02:58:03 +0100
commitff05d6ca35a6c193f8fa55a3470cea6acfbf7107 (patch)
treebedc1c505a5d3db884943fda5666f0e26ddaa543
parent056cce93db52af2f022a4e5c95d3c6afa07ad95c (diff)
downloadgtk+-ff05d6ca35a6c193f8fa55a3470cea6acfbf7107.tar.gz
gskslexpression: Add an "error" expression
Use it instead of initializing members to NULL and crashing later. The error expression also takes a type so that the parser can continue reporting potentially useful errors. Fixes a crash when initializers were used with too few members.
-rw-r--r--gsk/gskslexpression.c126
1 files changed, 99 insertions, 27 deletions
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 7be83504e0..51138a1588 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -89,6 +89,12 @@ gsk_sl_expression_default_is_assignable (const GskSlExpression *expression,
return FALSE;
}
+static GskSlValue *
+gsk_sl_expression_default_get_constant (const GskSlExpression *expression)
+{
+ return NULL;
+}
+
static GskSpvAccessChain *
gsk_sl_expression_default_get_spv_access_chain (const GskSlExpression *expression,
GskSpvWriter *writer)
@@ -143,12 +149,6 @@ gsk_sl_expression_assignment_get_return_type (const GskSlExpression *expression)
return gsk_sl_expression_get_return_type (assignment->lvalue);
}
-static GskSlValue *
-gsk_sl_expression_assignment_get_constant (const GskSlExpression *expression)
-{
- return NULL;
-}
-
static guint32
gsk_sl_expression_assignment_write_spv (const GskSlExpression *expression,
GskSpvWriter *writer)
@@ -188,7 +188,7 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
gsk_sl_expression_assignment_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_assignment_get_return_type,
- gsk_sl_expression_assignment_get_constant,
+ gsk_sl_expression_default_get_constant,
gsk_sl_expression_assignment_write_spv,
gsk_sl_expression_default_get_spv_access_chain
};
@@ -237,12 +237,6 @@ gsk_sl_expression_inc_dec_get_return_type (const GskSlExpression *expression)
return gsk_sl_expression_get_return_type (inc_dec->expr);
}
-static GskSlValue *
-gsk_sl_expression_inc_dec_get_constant (const GskSlExpression *expression)
-{
- return NULL;
-}
-
static guint32
gsk_sl_expression_inc_dec_write_spv (const GskSlExpression *expression,
GskSpvWriter *writer)
@@ -276,7 +270,7 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_INC_DEC = {
gsk_sl_expression_inc_dec_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_inc_dec_get_return_type,
- gsk_sl_expression_inc_dec_get_constant,
+ gsk_sl_expression_default_get_constant,
gsk_sl_expression_inc_dec_write_spv,
gsk_sl_expression_default_get_spv_access_chain
};
@@ -2162,16 +2156,85 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTANT = {
gsk_sl_expression_default_get_spv_access_chain
};
-/* If parsing fails completely, just assume 1.0 */
+/* ERROR */
+
+typedef struct _GskSlExpressionError GskSlExpressionError;
+
+struct _GskSlExpressionError {
+ GskSlExpression parent;
+
+ GskSlType *type;
+};
+
+static void
+gsk_sl_expression_error_free (GskSlExpression *expression)
+{
+ GskSlExpressionError *error = (GskSlExpressionError *) expression;
+
+ gsk_sl_type_unref (error->type);
+
+ g_slice_free (GskSlExpressionError, error);
+}
+
+static void
+gsk_sl_expression_error_print (const GskSlExpression *expression,
+ GskSlPrinter *printer)
+{
+ const GskSlExpressionError *error = (const GskSlExpressionError *) expression;
+ GskSlValue *value;
+
+ value = gsk_sl_value_new (error->type);
+ gsk_sl_value_print (value, printer);
+ gsk_sl_value_free (value);
+}
+
+static GskSlType *
+gsk_sl_expression_error_get_return_type (const GskSlExpression *expression)
+{
+ const GskSlExpressionError *error = (const GskSlExpressionError *) expression;
+
+ return error->type;
+}
+
+static guint32
+gsk_sl_expression_error_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ const GskSlExpressionError *error = (const GskSlExpressionError *) expression;
+ GskSlValue *value;
+ guint32 result_id;
+
+ value = gsk_sl_value_new (error->type);
+ result_id = gsk_spv_writer_get_id_for_value (writer, value);
+ gsk_sl_value_free (value);
+
+ return result_id;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_ERROR = {
+ gsk_sl_expression_error_free,
+ gsk_sl_expression_error_print,
+ gsk_sl_expression_default_is_assignable,
+ gsk_sl_expression_error_get_return_type,
+ gsk_sl_expression_default_get_constant,
+ gsk_sl_expression_error_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
+};
+
+/* If parsing fails, do not crash but behave as sanely as possible.
+ * This expression represents that case: It just has a type */
static GskSlExpression *
-gsk_sl_expression_error_new (void)
+gsk_sl_expression_error_new (GskSlType *type)
{
- GskSlExpressionConstant *constant;
+ GskSlExpressionError *error;
+
+ if (type == NULL)
+ type = gsk_sl_type_get_scalar (GSK_SL_FLOAT);
- constant = gsk_sl_expression_new (GskSlExpressionConstant, &GSK_SL_EXPRESSION_CONSTANT);
- constant->value = gsk_sl_value_new (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
+ error = gsk_sl_expression_new (GskSlExpressionError, &GSK_SL_EXPRESSION_ERROR);
+ error->type = gsk_sl_type_ref (type);
- return (GskSlExpression *) constant;
+ return (GskSlExpression *) error;
}
static GskSlExpression *
@@ -2196,7 +2259,7 @@ gsk_sl_expression_parse_constructor (GskSlScope *scope,
{
gsk_sl_preprocessor_error (stream, SYNTAX, "Expected opening \"(\" when calling function.");
gsk_sl_expression_unref ((GskSlExpression *) call);
- return gsk_sl_expression_error_new ();
+ return gsk_sl_expression_error_new (type);
}
gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
@@ -2282,7 +2345,7 @@ gsk_sl_expression_parse_constructor (GskSlScope *scope,
if (missing_args < 0)
{
gsk_sl_expression_unref ((GskSlExpression *) call);
- return gsk_sl_expression_error_new ();
+ return gsk_sl_expression_error_new (type);
}
return (GskSlExpression *) call;
@@ -2303,7 +2366,7 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
{
gsk_sl_preprocessor_error (stream, SYNTAX, "Expected opening \"(\" when calling function.");
gsk_sl_expression_unref ((GskSlExpression *) call);
- return gsk_sl_expression_error_new ();
+ return gsk_sl_expression_error_new (NULL);
}
gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
@@ -2382,7 +2445,7 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
if (matcher == NULL)
{
gsk_sl_expression_unref ((GskSlExpression *) call);
- return gsk_sl_expression_error_new ();
+ return gsk_sl_expression_error_new (NULL);
}
return (GskSlExpression *) call;
@@ -2448,7 +2511,7 @@ gsk_sl_expression_parse_primary (GskSlScope *scope,
if (variable == NULL)
{
gsk_sl_preprocessor_error (stream, DECLARATION, "No variable named \"%s\".", name);
- expr = gsk_sl_expression_error_new ();
+ expr = gsk_sl_expression_error_new (NULL);
}
else
{
@@ -2590,7 +2653,7 @@ gsk_sl_expression_parse_primary (GskSlScope *scope,
default:
gsk_sl_preprocessor_error (stream, SYNTAX, "Expected an expression.");
gsk_sl_preprocessor_consume (stream, NULL);
- return gsk_sl_expression_error_new ();
+ return gsk_sl_expression_error_new (NULL);
}
}
@@ -3680,8 +3743,13 @@ gsk_sl_expression_parse_initializer_array (GskSlScope *scope,
gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Cannot convert from %s to %s.",
gsk_sl_type_get_name (gsk_sl_expression_get_return_type (initializer->arguments[i])),
gsk_sl_type_get_name (index_type));
+ gsk_sl_expression_unref (initializer->arguments[i]);
+ initializer->arguments[i] = gsk_sl_expression_error_new (index_type);
}
}
+ /* in error case, sanitize this struct */
+ for (; i < initializer->n_arguments; i++)
+ initializer->arguments[i] = gsk_sl_expression_error_new (index_type);
return (GskSlExpression *) initializer;
}
@@ -3723,8 +3791,12 @@ gsk_sl_expression_parse_initializer_members (GskSlScope *scope,
gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Cannot convert from %s to %s.",
gsk_sl_type_get_name (gsk_sl_expression_get_return_type (initializer->arguments[i])),
gsk_sl_type_get_name (member_type));
+ gsk_sl_expression_unref (initializer->arguments[i]);
+ initializer->arguments[i] = gsk_sl_expression_error_new (gsk_sl_type_get_member_type (type, i));
}
}
+ for (; i < initializer->n_arguments; i++)
+ initializer->arguments[i] = gsk_sl_expression_error_new (gsk_sl_type_get_member_type (type, i));
return (GskSlExpression *) initializer;
}
@@ -3755,7 +3827,7 @@ gsk_sl_expression_parse_initializer (GskSlScope *scope,
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Cannot use initializer on %s", gsk_sl_type_get_name (type));
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACE);
- expression = gsk_sl_expression_error_new ();
+ expression = gsk_sl_expression_error_new (type);
}
token = gsk_sl_preprocessor_get (preproc);