зеркало из https://github.com/mozilla/gecko-dev.git
Fix 13413 - Require that the targets of length_is attributes have unsigned long type. There were a number of violations of this in the tree, so it turns out this was a useful one. Also add checks for missing parameters, length_is parameters that point to themselves, etc.
Fix 8833 - Allow typedefs in const declarations. Fix several warnings. Remove a huge chunk of #if 0 code in in xpidl_typelib.c (that had accumulated subsequent changes!)
This commit is contained in:
Родитель
c9bf929274
Коммит
3ad4f337ee
|
@ -197,6 +197,13 @@ xpidl_parse_iid(nsID *id, const char *str);
|
|||
(IDL_NODE_TYPE(node) == IDLN_IDENT && \
|
||||
UP_IS_AGGREGATE(node)))
|
||||
|
||||
/*
|
||||
* Find the underlying type of an identifier typedef. Returns NULL
|
||||
* (and doesn't complain) on failure.
|
||||
*/
|
||||
IDL_tree /* IDL_TYPE_DCL */
|
||||
find_underlying_type(IDL_tree typedef_ident);
|
||||
|
||||
/*
|
||||
* Check that scriptable attributes in scriptable interfaces actually are.
|
||||
*/
|
||||
|
|
|
@ -225,7 +225,6 @@ static gboolean
|
|||
doc_attribute_declaration(TreeState *state)
|
||||
{
|
||||
IDL_tree attr = state->tree;
|
||||
IDL_tree ident_list;
|
||||
|
||||
/*
|
||||
* Attribute idents can also take doc comments. They're ignored here;
|
||||
|
|
|
@ -686,6 +686,7 @@ do_const_dcl(TreeState *state)
|
|||
const char *name = IDL_IDENT(dcl->ident).str;
|
||||
gboolean success, is_signed;
|
||||
GSList *doc_comments = IDL_IDENT(dcl->ident).comments;
|
||||
IDL_tree real_type;
|
||||
|
||||
/* const -> list -> interface */
|
||||
if (!IDL_NODE_UP(IDL_NODE_UP(state->tree)) ||
|
||||
|
@ -697,9 +698,12 @@ do_const_dcl(TreeState *state)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(dcl->const_type));
|
||||
/* Could be a typedef; try to map it to the real type. */
|
||||
real_type = find_underlying_type(dcl->const_type);
|
||||
real_type = real_type ? real_type : dcl->const_type;
|
||||
success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(real_type));
|
||||
if (success) {
|
||||
switch(IDL_TYPE_INTEGER(dcl->const_type).f_type) {
|
||||
switch(IDL_TYPE_INTEGER(real_type).f_type) {
|
||||
case IDL_INTEGER_TYPE_SHORT:
|
||||
case IDL_INTEGER_TYPE_LONG:
|
||||
break;
|
||||
|
@ -707,7 +711,7 @@ do_const_dcl(TreeState *state)
|
|||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
is_signed = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
|
||||
is_signed = IDL_TYPE_INTEGER(real_type).f_signed;
|
||||
}
|
||||
|
||||
if (doc_comments != NULL) {
|
||||
|
|
|
@ -1115,6 +1115,7 @@ typelib_const_dcl(TreeState *state)
|
|||
const char *name = IDL_IDENT(dcl->ident).str;
|
||||
gboolean success;
|
||||
gboolean is_long;
|
||||
IDL_tree real_type;
|
||||
|
||||
/* const -> list -> interface */
|
||||
if (!IDL_NODE_UP(IDL_NODE_UP(state->tree)) ||
|
||||
|
@ -1126,9 +1127,12 @@ typelib_const_dcl(TreeState *state)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(dcl->const_type));
|
||||
/* Could be a typedef; try to map it to the real type. */
|
||||
real_type = find_underlying_type(dcl->const_type);
|
||||
real_type = real_type ? real_type : dcl->const_type;
|
||||
success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(real_type));
|
||||
if(success) {
|
||||
switch(IDL_TYPE_INTEGER(dcl->const_type).f_type) {
|
||||
switch(IDL_TYPE_INTEGER(real_type).f_type) {
|
||||
case IDL_INTEGER_TYPE_SHORT:
|
||||
is_long = FALSE;
|
||||
break;
|
||||
|
@ -1180,99 +1184,6 @@ typelib_const_dcl(TreeState *state)
|
|||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
#if 0
|
||||
XPTInterfaceDescriptor *id;
|
||||
XPTConstDescriptor *cd;
|
||||
struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
|
||||
|
||||
/* const -> list -> interface */
|
||||
if (IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(state->tree)))
|
||||
!= IDLN_INTERFACE) {
|
||||
XPIDL_WARNING((state->tree, IDL_WARNING1,
|
||||
"const decl not inside interface!\n"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
id = CURRENT(state);
|
||||
if (!XPT_InterfaceDescriptorAddConsts(ARENA(state), id, 1))
|
||||
return FALSE;
|
||||
cd = &id->const_descriptors[NEXT_CONST(state)];
|
||||
|
||||
cd->name = IDL_IDENT(dcl->ident).str;
|
||||
#ifdef DEBUG_shaver_const
|
||||
fprintf(stderr, "DBG: adding const %s\n", cd->name);
|
||||
#endif
|
||||
|
||||
if (!fill_td_from_type(state, &cd->type, dcl->const_type))
|
||||
return FALSE;
|
||||
|
||||
switch (IDL_NODE_TYPE(dcl->const_type)) {
|
||||
case IDLN_TYPE_INTEGER: {
|
||||
IDL_longlong_t value = IDL_INTEGER(dcl->const_exp).value;
|
||||
gboolean sign = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
|
||||
switch(IDL_TYPE_INTEGER(dcl->const_type).f_type) {
|
||||
case IDL_INTEGER_TYPE_SHORT:
|
||||
if(sign)
|
||||
cd->value.i16 = value;
|
||||
else
|
||||
cd->value.ui16 = value;
|
||||
break;
|
||||
case IDL_INTEGER_TYPE_LONG:
|
||||
if(sign)
|
||||
cd->value.i32 = value;
|
||||
else
|
||||
cd->value.ui32 = value;
|
||||
break;
|
||||
case IDL_INTEGER_TYPE_LONGLONG:
|
||||
/* XXXshaver value -> PRInt64 not legal conversion? */
|
||||
if (sign)
|
||||
LL_I2L(cd->value.i64, value);
|
||||
else
|
||||
LL_UI2L(cd->value.ui64, value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDLN_TYPE_CHAR:
|
||||
cd->value.ch = IDL_CHAR(dcl->const_exp).value[0];
|
||||
XPT_ASSERT(cd->value.ch);
|
||||
break;
|
||||
case IDLN_TYPE_WIDE_CHAR:
|
||||
cd->value.wch = IDL_WIDE_CHAR(dcl->const_exp).value[0];
|
||||
XPT_ASSERT(cd->value.wch);
|
||||
break;
|
||||
case IDLN_TYPE_STRING:
|
||||
cd->value.string = XPT_NewStringZ(ARENA(state),
|
||||
IDL_STRING(dcl->const_exp).value);
|
||||
if (!cd->value.string)
|
||||
return FALSE;
|
||||
break;
|
||||
case IDLN_TYPE_WIDE_STRING:
|
||||
XPT_ASSERT(0);
|
||||
break;
|
||||
case IDLN_TYPE_BOOLEAN:
|
||||
cd->value.bul = IDL_BOOLEAN(dcl->const_exp).value;
|
||||
break;
|
||||
case IDLN_TYPE_FLOAT:
|
||||
cd->value.flt = (float)IDL_FLOAT(dcl->const_exp).value;
|
||||
break;
|
||||
#if 0 /* IDL doesn't have double */
|
||||
case IDLN_TYPE_DOUBLE:
|
||||
cd->value.dbl = IDL_FLOAT(dcl->const_exp).value;
|
||||
#endif
|
||||
break;
|
||||
case IDLN_IDENT:
|
||||
/* XXX check for nsID? */
|
||||
break;
|
||||
default:
|
||||
IDL_tree_error(state->tree, "illegal type for const\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NEXT_CONST(state)++;
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -201,6 +201,141 @@ verify_attribute_declaration(IDL_tree attr_tree)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the underlying type of an identifier typedef.
|
||||
*
|
||||
* All the needed tree-walking seems pretty shaky; isn't there something in
|
||||
* libIDL to automate this?
|
||||
* Might want to export this to handle the bug against no typedef'd const.
|
||||
*/
|
||||
IDL_tree /* IDL_TYPE_DCL */
|
||||
find_underlying_type(IDL_tree typedef_ident)
|
||||
{
|
||||
IDL_tree up;
|
||||
IDL_tree type;
|
||||
|
||||
if (typedef_ident == NULL || IDL_NODE_TYPE(typedef_ident) != IDLN_IDENT)
|
||||
return NULL;
|
||||
|
||||
up = IDL_NODE_UP(typedef_ident);
|
||||
if (up == NULL || IDL_NODE_TYPE(up) != IDLN_LIST)
|
||||
return NULL;
|
||||
up = IDL_NODE_UP(up);
|
||||
if (up == NULL || IDL_NODE_TYPE(up) != IDLN_TYPE_DCL)
|
||||
return NULL;
|
||||
|
||||
return IDL_TYPE_DCL(up).type_spec;
|
||||
}
|
||||
|
||||
static IDL_tree /* IDL_PARAM_DCL */
|
||||
find_named_parameter(IDL_tree method_tree, const char *param_name)
|
||||
{
|
||||
IDL_tree iter;
|
||||
for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter;
|
||||
iter = IDL_LIST(iter).next)
|
||||
{
|
||||
IDL_tree param = IDL_LIST(iter).data;
|
||||
IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
|
||||
const char *current_name = IDL_IDENT(simple_decl).str;
|
||||
if (strcmp(current_name, param_name) == 0)
|
||||
return param;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef enum ParamAttrType {
|
||||
IID_IS,
|
||||
LENGTH_IS,
|
||||
SIZE_IS
|
||||
} ParamAttrType;
|
||||
|
||||
/*
|
||||
* Check that parameters referred to by attributes such as size_is exist and
|
||||
* refer to parameters of the appropriate type.
|
||||
*/
|
||||
static gboolean
|
||||
check_param_attribute(IDL_tree method_tree, IDL_tree param,
|
||||
ParamAttrType whattocheck)
|
||||
{
|
||||
const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
|
||||
const char *referred_name = NULL;
|
||||
IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec;
|
||||
IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
|
||||
const char *param_name = IDL_IDENT(simple_decl).str;
|
||||
const char *attr_name;
|
||||
const char *needed_type;
|
||||
|
||||
if (whattocheck == IID_IS) {
|
||||
attr_name = "iid_is";
|
||||
needed_type = "IID";
|
||||
} else if (whattocheck == LENGTH_IS) {
|
||||
attr_name = "length_is";
|
||||
needed_type = "unsigned long (or PRUint32)";
|
||||
} else if (whattocheck == SIZE_IS) {
|
||||
attr_name = "size_is";
|
||||
needed_type = "unsigned long (or PRUint32)";
|
||||
} else {
|
||||
assert("asked to check an unknown attribute type!");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
referred_name = IDL_tree_property_get(simple_decl, attr_name);
|
||||
if (referred_name != NULL) {
|
||||
IDL_tree referred_param = find_named_parameter(method_tree,
|
||||
referred_name);
|
||||
IDL_tree referred_param_type;
|
||||
if (referred_param == NULL) {
|
||||
IDL_tree_error(method_tree,
|
||||
"attribute [%s(%s)] refers to missing "
|
||||
"parameter \"%s\"",
|
||||
attr_name, referred_name, referred_name);
|
||||
return FALSE;
|
||||
}
|
||||
if (referred_param == param) {
|
||||
IDL_tree_error(method_tree,
|
||||
"attribute [%s(%s)] refers to it's own parameter",
|
||||
attr_name, referred_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec;
|
||||
if (whattocheck == IID_IS) {
|
||||
/* require IID type */
|
||||
if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) {
|
||||
IDL_tree_error(method_tree,
|
||||
"target \"%s\" of [%s(%s)] attribute "
|
||||
"must be of %s type",
|
||||
referred_name, attr_name, referred_name,
|
||||
needed_type);
|
||||
return FALSE;
|
||||
}
|
||||
} else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) {
|
||||
/* require PRUint32 type */
|
||||
IDL_tree real_type;
|
||||
|
||||
/* Could be a typedef; try to map it to the real type. */
|
||||
real_type = find_underlying_type(referred_param_type);
|
||||
real_type = real_type ? real_type : referred_param_type;
|
||||
|
||||
if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER ||
|
||||
IDL_TYPE_INTEGER(real_type).f_signed != FALSE ||
|
||||
IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG)
|
||||
{
|
||||
IDL_tree_error(method_tree,
|
||||
"target \"%s\" of [%s(%s)] attribute "
|
||||
"must be of %s type",
|
||||
referred_name, attr_name, referred_name,
|
||||
needed_type);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Common method verification code, called by *op_dcl in the various backends.
|
||||
*/
|
||||
|
@ -209,11 +344,14 @@ verify_method_declaration(IDL_tree method_tree)
|
|||
{
|
||||
struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
|
||||
IDL_tree iface;
|
||||
IDL_tree iter;
|
||||
gboolean scriptable_interface;
|
||||
gboolean scriptable_method;
|
||||
const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
|
||||
|
||||
if (op->f_varargs) {
|
||||
/* We don't currently support varargs. */
|
||||
IDL_tree_error(method_tree, "varargs are not currently supported\n");
|
||||
IDL_tree_error(method_tree, "varargs are not currently supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -238,46 +376,59 @@ verify_method_declaration(IDL_tree method_tree)
|
|||
* Require that any method in an interface marked as [scriptable], that
|
||||
* *isn't* scriptable because it refers to some native type, be marked
|
||||
* [noscript] or [notxpcom].
|
||||
*
|
||||
* Also check that iid_is points to nsid, and length_is, size_is points
|
||||
* to unsigned long.
|
||||
*/
|
||||
if (scriptable_interface &&
|
||||
scriptable_method = scriptable_interface &&
|
||||
IDL_tree_property_get(op->ident, "notxpcom") == NULL &&
|
||||
IDL_tree_property_get(op->ident, "noscript") == NULL)
|
||||
{
|
||||
IDL_tree iter;
|
||||
IDL_tree_property_get(op->ident, "noscript") == NULL;
|
||||
|
||||
/* Loop through the parameters and check. */
|
||||
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
|
||||
IDL_tree param_type =
|
||||
IDL_PARAM_DCL(IDL_LIST(iter).data).param_type_spec;
|
||||
IDL_tree simple_decl =
|
||||
IDL_PARAM_DCL(IDL_LIST(iter).data).simple_declarator;
|
||||
|
||||
/*
|
||||
* Reject this method if a parameter is native and isn't marked
|
||||
* with either nsid or iid_is.
|
||||
*/
|
||||
if (UP_IS_NATIVE(param_type) &&
|
||||
IDL_tree_property_get(param_type, "nsid") == NULL &&
|
||||
IDL_tree_property_get(simple_decl, "iid_is") == NULL)
|
||||
{
|
||||
IDL_tree_error(method_tree,
|
||||
"methods in [scriptable] interfaces which are "
|
||||
"non-scriptable because they refer to native "
|
||||
"types (parameter \"%s\") must be marked "
|
||||
"[noscript]\n", IDL_IDENT(simple_decl).str);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/* Loop through the parameters and check. */
|
||||
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
|
||||
IDL_tree param = IDL_LIST(iter).data;
|
||||
IDL_tree param_type =
|
||||
IDL_PARAM_DCL(param).param_type_spec;
|
||||
IDL_tree simple_decl =
|
||||
IDL_PARAM_DCL(param).simple_declarator;
|
||||
const char *param_name = IDL_IDENT(simple_decl).str;
|
||||
|
||||
/* How about the return type? */
|
||||
if (op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec)) {
|
||||
/*
|
||||
* Reject this method if it should be scriptable and some parameter is
|
||||
* native that isn't marked with either nsid or iid_is.
|
||||
*/
|
||||
if (scriptable_method &&
|
||||
UP_IS_NATIVE(param_type) &&
|
||||
IDL_tree_property_get(param_type, "nsid") == NULL &&
|
||||
IDL_tree_property_get(simple_decl, "iid_is") == NULL)
|
||||
{
|
||||
IDL_tree_error(method_tree,
|
||||
"methods in [scriptable] interfaces which are "
|
||||
"non-scriptable because they return native "
|
||||
"types must be marked [noscript]\n");
|
||||
"non-scriptable because they refer to native "
|
||||
"types (parameter \"%s\") must be marked "
|
||||
"[noscript]", param_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!check_param_attribute(method_tree, param, IID_IS) ||
|
||||
!check_param_attribute(method_tree, param, LENGTH_IS) ||
|
||||
!check_param_attribute(method_tree, param, SIZE_IS))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* XXX q: can return type be nsid? */
|
||||
/* Native return type? */
|
||||
if (scriptable_method &&
|
||||
op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) &&
|
||||
IDL_tree_property_get(op->op_type_spec, "nsid") == NULL)
|
||||
{
|
||||
IDL_tree_error(method_tree,
|
||||
"methods in [scriptable] interfaces which are "
|
||||
"non-scriptable because they return native "
|
||||
"types must be marked [noscript]");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче