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:
mccabe%netscape.com 2000-04-28 11:14:29 +00:00
Родитель c9bf929274
Коммит 3ad4f337ee
5 изменённых файлов: 203 добавлений и 131 удалений

Просмотреть файл

@ -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;
}