Merge pull request #98 from alliedmodders/fix-nullable
Fix nullable comparisons.
This commit is contained in:
commit
b84b70d0f1
@ -672,8 +672,9 @@ SC_FUNC symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength);
|
||||
SC_FUNC int getlabel(void);
|
||||
SC_FUNC char *itoh(ucell val);
|
||||
|
||||
#define MATCHTAG_COERCE 0x1 // allow coercion
|
||||
#define MATCHTAG_SILENT 0x2 // silence the error(213) warning
|
||||
#define MATCHTAG_COERCE 0x1 // allow coercion
|
||||
#define MATCHTAG_SILENT 0x2 // silence the error(213) warning
|
||||
#define MATCHTAG_COMMUTATIVE 0x4 // order does not matter
|
||||
|
||||
/* function prototypes in SC3.C */
|
||||
SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
|
||||
|
@ -4056,7 +4056,7 @@ static void domethodmap(LayoutSpec spec)
|
||||
if (spec == Layout_MethodMap) {
|
||||
map->tag = pc_addtag_flags(mapname, FIXEDTAG | METHODMAPTAG);
|
||||
|
||||
if (matchtoken(tNULLABLE))
|
||||
if (matchtoken(tNULLABLE) || (parent && parent->nullable))
|
||||
map->nullable = TRUE;
|
||||
} else {
|
||||
constvalue *tagptr = pc_tagptr(mapname);
|
||||
|
@ -353,6 +353,15 @@ static int obj_typeerror(int id, int tag1, int tag2)
|
||||
|
||||
static int matchobjecttags(int formaltag, int actualtag, int flags)
|
||||
{
|
||||
if ((flags & MATCHTAG_COMMUTATIVE) &&
|
||||
(formaltag == pc_tag_null_t || formaltag == pc_tag_nullfunc_t))
|
||||
{
|
||||
// Bypass the check immediately after for non-object coercion.
|
||||
int tmp = actualtag;
|
||||
actualtag = formaltag;
|
||||
formaltag = tmp;
|
||||
}
|
||||
|
||||
// objects never coerce to non-objects, YET.
|
||||
if ((formaltag & OBJECTTAG) && !(actualtag & OBJECTTAG))
|
||||
return obj_typeerror(132, formaltag, actualtag);
|
||||
@ -372,12 +381,11 @@ static int matchobjecttags(int formaltag, int actualtag, int flags)
|
||||
if (formaltag & OBJECTTAG)
|
||||
return TRUE;
|
||||
|
||||
// Some methodmaps are nullable.
|
||||
// Some methodmaps are nullable. The nullable property is inherited
|
||||
// automatically.
|
||||
methodmap_t *map = methodmap_find_by_tag(formaltag);
|
||||
for (; map; map = map->parent) {
|
||||
if (map->nullable)
|
||||
return TRUE;
|
||||
}
|
||||
if (map->nullable)
|
||||
return TRUE;
|
||||
|
||||
error(148, pc_tagname(formaltag));
|
||||
return FALSE;
|
||||
@ -923,8 +931,9 @@ static void plnge2(void (*oper)(void),
|
||||
matchtag(lval1->tag,lval2->tag,FALSE);
|
||||
lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult);
|
||||
} else {
|
||||
// For the purposes of tag matching, we consider the order to be irrelevant.
|
||||
if (!checktag_string(lval1, lval2))
|
||||
matchtag(lval1->tag,lval2->tag,FALSE);
|
||||
matchtag(lval1->tag, lval2->tag, MATCHTAG_COMMUTATIVE);
|
||||
(*oper)(); /* do the (signed) operation */
|
||||
lval1->ident=iEXPRESSION;
|
||||
} /* if */
|
||||
|
19
sourcepawn/compiler/tests/ok-null-compare.sp
Normal file
19
sourcepawn/compiler/tests/ok-null-compare.sp
Normal file
@ -0,0 +1,19 @@
|
||||
enum Handle:
|
||||
{
|
||||
}
|
||||
|
||||
methodmap Handle __nullable__
|
||||
{
|
||||
}
|
||||
|
||||
methodmap StringMap < Handle
|
||||
{
|
||||
}
|
||||
|
||||
native Log(const char[] fmt, any:...)
|
||||
|
||||
public main()
|
||||
{
|
||||
StringMap f
|
||||
Log("hello %d", f != null)
|
||||
}
|
Loading…
Reference in New Issue
Block a user