aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/c-common.c32
-rw-r--r--gcc/c-decl.c43
-rw-r--r--gcc/c-typeck.c124
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/Wwrite-strings-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/array-quals-2.c14
-rw-r--r--gcc/testsuite/gcc.dg/concat.c4
-rw-r--r--gcc/testsuite/gcc.dg/lvalue-3.c14
9 files changed, 188 insertions, 80 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d0f51a0..3edb615 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,26 @@
+2005-01-29 Joseph S. Myers <joseph@codesourcery.com>
+
+ * c-common.c (fix_string_type): Just use c_build_qualified_type to
+ build string type.
+ (c_build_qualified_type): Build qualified array types with
+ TYPE_MAIN_VARIANT pointing to corresponding unqualified type.
+ * c-decl.c (c_make_fname_decl): Build unqualified array type
+ before qualified type.
+ (grokdeclarator): Use TYPE_MAIN_VARIANT of typedef type if element
+ type is qualified, not just if type itself is. Don't apply
+ qualifiers to array type when declarator is processed. Apply
+ qualifiers to field type whether or not it is an array type.
+ Don't handle array types specially for applying qualifiers to
+ variables.
+ * c-typeck.c (composite_type): Build unqualified element type and
+ array type when forming composite of array types.
+ (common_pointer_type, comptypes, comp_target_types,
+ type_lists_compatible_p, build_indirect_ref, build_array_ref,
+ convert_for_assignment): Don't apply TYPE_MAIN_VARIANT to array
+ types.
+ (type_lists_compatible_p): Cache TREE_VALUE (args1) and TREE_VALUE
+ (args2) in variables a1 and a2.
+
2005-01-29 Kazu Hirata <kazu@cs.umass.edu>
* cse.c (n_elements_made, max_elements_made): Remove.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 1df71ad..72fd846 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -862,12 +862,7 @@ fix_string_type (tree value)
i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1));
a_type = build_array_type (e_type, i_type);
if (flag_const_strings)
- {
- /* bleah, c_build_qualified_type should set TYPE_MAIN_VARIANT. */
- tree qa_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
- TYPE_MAIN_VARIANT (qa_type) = a_type;
- a_type = qa_type;
- }
+ a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
TREE_TYPE (value) = a_type;
TREE_CONSTANT (value) = 1;
@@ -2483,9 +2478,28 @@ c_build_qualified_type (tree type, int type_quals)
return type;
if (TREE_CODE (type) == ARRAY_TYPE)
- return build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
+ {
+ tree t;
+ tree element_type = c_build_qualified_type (TREE_TYPE (type),
+ type_quals);
+
+ /* See if we already have an identically qualified type. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ {
+ if (TYPE_QUALS (strip_array_types (t)) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+ && attribute_list_equal (TYPE_ATTRIBUTES (t),
+ TYPE_ATTRIBUTES (type)))
+ break;
+ }
+ if (!t)
+ {
+ t = build_variant_type_copy (type);
+ TREE_TYPE (t) = element_type;
+ }
+ return t;
+ }
/* A restrict-qualified pointer type must be a pointer to object or
incomplete type. Note that the use of POINTER_TYPE_P also allows
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 6e8c742..efb17e8 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2632,9 +2632,9 @@ c_make_fname_decl (tree id, int type_dep)
tree decl, type, init;
size_t length = strlen (name);
- type = build_array_type
- (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
- build_index_type (size_int (length)));
+ type = build_array_type (char_type_node,
+ build_index_type (size_int (length)));
+ type = c_build_qualified_type (type, TYPE_QUAL_CONST);
decl = build_decl (VAR_DECL, id, type);
@@ -3861,7 +3861,7 @@ grokdeclarator (const struct c_declarator *declarator,
if (volatilep > 1)
pedwarn ("duplicate %<volatile%>");
}
- if (!flag_gen_aux_info && (TYPE_QUALS (type)))
+ if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
@@ -3946,7 +3946,13 @@ grokdeclarator (const struct c_declarator *declarator,
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an absolute declarator). */
+ the declared identifier (or NULL_TREE, in an absolute declarator).
+ At each stage we maintain an unqualified version of the type
+ together with any qualifiers that should be applied to it with
+ c_build_qualified_type; this way, array types including
+ multidimensional array types are first built up in unqualified
+ form and then the qualified form is created with
+ TYPE_MAIN_VARIANT pointing to the unqualified form. */
while (declarator && declarator->kind != cdk_id)
{
@@ -4146,13 +4152,7 @@ grokdeclarator (const struct c_declarator *declarator,
if (pedantic && !COMPLETE_TYPE_P (type))
pedwarn ("array type has incomplete element type");
- /* Build the array type itself, then merge any constancy
- or volatility into the target type. We must do it in
- this order to ensure that the TYPE_MAIN_VARIANT field
- of the array type is set correctly. */
type = build_array_type (type, itype);
- if (type_quals)
- type = c_build_qualified_type (type, type_quals);
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
@@ -4278,7 +4278,8 @@ grokdeclarator (const struct c_declarator *declarator,
}
}
- /* Now TYPE has the actual type. */
+ /* Now TYPE has the actual type, apart from any qualifiers in
+ TYPE_QUALS. */
/* Check the type and width of a bit-field. */
if (bitfield)
@@ -4447,11 +4448,7 @@ grokdeclarator (const struct c_declarator *declarator,
error ("field %qs has incomplete type", name);
type = error_mark_node;
}
- /* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
+ type = c_build_qualified_type (type, type_quals);
decl = build_decl (FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
@@ -4556,17 +4553,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern;
- /* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- {
- int saved_align = TYPE_ALIGN(type);
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
- TYPE_ALIGN (type) = saved_align;
- }
- else if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals);
/* C99 6.2.2p7: It is invalid (compile-time undefined
behavior) to create an 'extern' declaration for a
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index cb657df..fed17f2 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -277,7 +277,9 @@ composite_type (tree t1, tree t2)
case ARRAY_TYPE:
{
tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
-
+ int quals;
+ tree unqual_elt;
+
/* We should not have any type quals on arrays at all. */
gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
@@ -292,8 +294,16 @@ composite_type (tree t1, tree t2)
if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
return build_type_attribute_variant (t2, attributes);
- /* Merge the element types, and have a size if either arg has one. */
- t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ /* Merge the element types, and have a size if either arg has
+ one. We may have qualifiers on the element types. To set
+ up TYPE_MAIN_VARIANT correctly, we need to form the
+ composite of the unqualified types and add the qualifiers
+ back at the end. */
+ quals = TYPE_QUALS (strip_array_types (elt));
+ unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+ t1 = build_array_type (unqual_elt,
+ TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ t1 = c_build_qualified_type (t1, quals);
return build_type_attribute_variant (t1, attributes);
}
@@ -415,8 +425,8 @@ static tree
common_pointer_type (tree t1, tree t2)
{
tree attributes;
- tree pointed_to_1;
- tree pointed_to_2;
+ tree pointed_to_1, mv1;
+ tree pointed_to_2, mv2;
tree target;
/* Save time if the two types are the same. */
@@ -436,11 +446,15 @@ common_pointer_type (tree t1, tree t2)
attributes = targetm.merge_type_attributes (t1, t2);
/* Find the composite type of the target types, and combine the
- qualifiers of the two types' targets. */
- pointed_to_1 = TREE_TYPE (t1);
- pointed_to_2 = TREE_TYPE (t2);
- target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
- TYPE_MAIN_VARIANT (pointed_to_2));
+ qualifiers of the two types' targets. Do not lose qualifiers on
+ array element types by taking the TYPE_MAIN_VARIANT. */
+ mv1 = pointed_to_1 = TREE_TYPE (t1);
+ mv2 = pointed_to_2 = TREE_TYPE (t2);
+ if (TREE_CODE (mv1) != ARRAY_TYPE)
+ mv1 = TYPE_MAIN_VARIANT (pointed_to_1);
+ if (TREE_CODE (mv2) != ARRAY_TYPE)
+ mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
+ target = composite_type (mv1, mv2);
t1 = build_pointer_type (c_build_qualified_type
(target,
TYPE_QUALS (pointed_to_1) |
@@ -632,7 +646,8 @@ comptypes (tree type1, tree type2)
definition. Note that we already checked for equality of the type
qualifiers (just above). */
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ if (TREE_CODE (t1) != ARRAY_TYPE
+ && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
@@ -734,13 +749,21 @@ static int
comp_target_types (tree ttl, tree ttr, int reflexive)
{
int val;
+ tree mvl, mvr;
/* Give objc_comptypes a crack at letting these types through. */
if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
return val;
- val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
- TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
+ /* Do not lose qualifiers on element types of array types that are
+ pointer targets by taking their TYPE_MAIN_VARIANT. */
+ mvl = TREE_TYPE (ttl);
+ mvr = TREE_TYPE (ttr);
+ if (TREE_CODE (mvl) != ARRAY_TYPE)
+ mvl = TYPE_MAIN_VARIANT (mvl);
+ if (TREE_CODE (mvr) != ARRAY_TYPE)
+ mvr = TYPE_MAIN_VARIANT (mvr);
+ val = comptypes (mvl, mvr);
if (val == 2 && pedantic)
pedwarn ("types are not quite compatible");
@@ -1042,61 +1065,67 @@ type_lists_compatible_p (tree args1, tree args2)
while (1)
{
+ tree a1, mv1, a2, mv2;
if (args1 == 0 && args2 == 0)
return val;
/* If one list is shorter than the other,
they fail to match. */
if (args1 == 0 || args2 == 0)
return 0;
+ mv1 = a1 = TREE_VALUE (args1);
+ mv2 = a2 = TREE_VALUE (args2);
+ if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
+ mv1 = TYPE_MAIN_VARIANT (mv1);
+ if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
+ mv2 = TYPE_MAIN_VARIANT (mv2);
/* A null pointer instead of a type
means there is supposed to be an argument
but nothing is specified about what type it has.
So match anything that self-promotes. */
- if (TREE_VALUE (args1) == 0)
+ if (a1 == 0)
{
- if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2))
+ if (c_type_promotes_to (a2) != a2)
return 0;
}
- else if (TREE_VALUE (args2) == 0)
+ else if (a2 == 0)
{
- if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1))
+ if (c_type_promotes_to (a1) != a1)
return 0;
}
/* If one of the lists has an error marker, ignore this arg. */
- else if (TREE_CODE (TREE_VALUE (args1)) == ERROR_MARK
- || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK)
+ else if (TREE_CODE (a1) == ERROR_MARK
+ || TREE_CODE (a2) == ERROR_MARK)
;
- else if (!(newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
- TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
+ else if (!(newval = comptypes (mv1, mv2)))
{
/* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */
- if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE
- && (TYPE_NAME (TREE_VALUE (args1)) == 0
- || TYPE_TRANSPARENT_UNION (TREE_VALUE (args1)))
- && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST
- && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)),
- TYPE_SIZE (TREE_VALUE (args2))))
+ if (TREE_CODE (a1) == UNION_TYPE
+ && (TYPE_NAME (a1) == 0
+ || TYPE_TRANSPARENT_UNION (a1))
+ && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
+ && tree_int_cst_equal (TYPE_SIZE (a1),
+ TYPE_SIZE (a2)))
{
tree memb;
- for (memb = TYPE_FIELDS (TREE_VALUE (args1));
+ for (memb = TYPE_FIELDS (a1);
memb; memb = TREE_CHAIN (memb))
- if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2)))
+ if (comptypes (TREE_TYPE (memb), a2))
break;
if (memb == 0)
return 0;
}
- else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE
- && (TYPE_NAME (TREE_VALUE (args2)) == 0
- || TYPE_TRANSPARENT_UNION (TREE_VALUE (args2)))
- && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST
- && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)),
- TYPE_SIZE (TREE_VALUE (args1))))
+ else if (TREE_CODE (a2) == UNION_TYPE
+ && (TYPE_NAME (a2) == 0
+ || TYPE_TRANSPARENT_UNION (a2))
+ && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
+ && tree_int_cst_equal (TYPE_SIZE (a2),
+ TYPE_SIZE (a1)))
{
tree memb;
- for (memb = TYPE_FIELDS (TREE_VALUE (args2));
+ for (memb = TYPE_FIELDS (a2);
memb; memb = TREE_CHAIN (memb))
- if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1)))
+ if (comptypes (TREE_TYPE (memb), a1))
break;
if (memb == 0)
return 0;
@@ -1542,7 +1571,12 @@ build_indirect_ref (tree ptr, const char *errorstring)
else
{
tree t = TREE_TYPE (type);
- tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer);
+ tree mvt = t;
+ tree ref;
+
+ if (TREE_CODE (mvt) != ARRAY_TYPE)
+ mvt = TYPE_MAIN_VARIANT (mvt);
+ ref = build1 (INDIRECT_REF, mvt, pointer);
if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
{
@@ -1670,7 +1704,9 @@ build_array_ref (tree array, tree index)
pedwarn ("ISO C90 forbids subscripting non-lvalue array");
}
- type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
+ type = TREE_TYPE (TREE_TYPE (array));
+ if (TREE_CODE (type) != ARRAY_TYPE)
+ type = TYPE_MAIN_VARIANT (type);
rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
/* Array ref is const/volatile if the array elements are
or if the array is. */
@@ -3597,9 +3633,15 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
{
tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype);
+ tree mvl = ttl;
+ tree mvr = ttr;
bool is_opaque_pointer;
int target_cmp = 0; /* Cache comp_target_types () result. */
+ if (TREE_CODE (mvl) != ARRAY_TYPE)
+ mvl = TYPE_MAIN_VARIANT (mvl);
+ if (TREE_CODE (mvr) != ARRAY_TYPE)
+ mvr = TYPE_MAIN_VARIANT (mvr);
/* Opaque pointers are treated like void pointers. */
is_opaque_pointer = (targetm.vector_opaque_p (type)
|| targetm.vector_opaque_p (rhstype))
@@ -3612,8 +3654,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| (target_cmp = comp_target_types (type, rhstype, 0))
|| is_opaque_pointer
- || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl))
- == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr))))
+ || (c_common_unsigned_type (mvl)
+ == c_common_unsigned_type (mvr)))
{
if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2fc135f..e7ff37e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2005-01-29 Joseph S. Myers <joseph@codesourcery.com>
+
+ * gcc.dg/Wwrite-strings-1.c, gcc.dg/array-quals-2.c,
+ gcc.dg/lvalue-3.c: New tests.
+ * gcc.dg/concat.c: Update expected messages.
+
2005-01-29 Thomas Koenig <Thomas.Koenig@online.de>
PR libfortran/19595
diff --git a/gcc/testsuite/gcc.dg/Wwrite-strings-1.c b/gcc/testsuite/gcc.dg/Wwrite-strings-1.c
new file mode 100644
index 0000000..9270e8f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wwrite-strings-1.c
@@ -0,0 +1,8 @@
+/* Test pointer initialization and dereference don't lose qualifiers
+ on array types. This test wrongly failed to diagnose the loss of
+ const. */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "-Wwrite-strings" } */
+typedef char T[1];
+T *p = &""; /* { dg-warning "warning: initialization from incompatible pointer type" } */
diff --git a/gcc/testsuite/gcc.dg/array-quals-2.c b/gcc/testsuite/gcc.dg/array-quals-2.c
new file mode 100644
index 0000000..5d20244
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/array-quals-2.c
@@ -0,0 +1,14 @@
+/* Test that pointers to arrays of differently qualified types aren't
+ permitted in conditional expressions, and that qualifiers aren't
+ lost in forming composite types. */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+typedef const char T[1];
+typedef const char T2[1];
+typedef volatile char U[1];
+T *p;
+T2 *p2;
+U *q;
+void *f(void) { return 1 ? p : q; } /* { dg-warning "warning: pointer type mismatch in conditional expression" } */
+T *g(void) { return 1 ? p : p2; }
diff --git a/gcc/testsuite/gcc.dg/concat.c b/gcc/testsuite/gcc.dg/concat.c
index 9503368..0b9d6f6 100644
--- a/gcc/testsuite/gcc.dg/concat.c
+++ b/gcc/testsuite/gcc.dg/concat.c
@@ -8,8 +8,8 @@
void foo ()
{
- char s1[] = __FUNCTION__"."; /* { dg-error "(parse|syntax|expected|invalid)" } */
- char s2[] = __PRETTY_FUNCTION__".";/* { dg-error "(parse|syntax|expected|invalid)" } */
+ char s1[] = __FUNCTION__"."; /* { dg-error "(parse|syntax|expected|invalid|array)" } */
+ char s2[] = __PRETTY_FUNCTION__".";/* { dg-error "(parse|syntax|expected|invalid|array)" } */
char s3[] = "."__FUNCTION__; /* { dg-error "(parse|syntax|expected|invalid)" } */
char s4[] = "."__PRETTY_FUNCTION__;/* { dg-error "(parse|syntax|expected|invalid)" } */
char s5[] = ".""."; /* No error. */
diff --git a/gcc/testsuite/gcc.dg/lvalue-3.c b/gcc/testsuite/gcc.dg/lvalue-3.c
new file mode 100644
index 0000000..0745c7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lvalue-3.c
@@ -0,0 +1,14 @@
+/* Test that assignment of a read-only variable that gets const-ness
+ from a read-only field is diagnosed. */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct s { const int a; } x;
+typeof (x.a) b;
+void
+f (void)
+{
+ x.a = 1; /* { dg-error "error: assignment of read-only member 'a'" } */
+ b = 1; /* { dg-error "error: assignment of read-only variable 'b'" } */
+}