Implement operators __static_assert
and __static_check
This commit is contained in:
parent
3dfad1f7fd
commit
903c06253e
@ -420,6 +420,8 @@ enum {
|
|||||||
tSLEEP,
|
tSLEEP,
|
||||||
tSTATE,
|
tSTATE,
|
||||||
tSTATIC,
|
tSTATIC,
|
||||||
|
t__STATIC_ASSERT,
|
||||||
|
t__STATIC_CHECK,
|
||||||
tSTOCK,
|
tSTOCK,
|
||||||
tSWITCH,
|
tSWITCH,
|
||||||
tTAGOF,
|
tTAGOF,
|
||||||
@ -704,6 +706,7 @@ SC_FUNC void emit_parse_line(void);
|
|||||||
SC_FUNC void pragma_deprecated(symbol *sym);
|
SC_FUNC void pragma_deprecated(symbol *sym);
|
||||||
SC_FUNC void pragma_unused(symbol *sym,int unread,int unwritten);
|
SC_FUNC void pragma_unused(symbol *sym,int unread,int unwritten);
|
||||||
SC_FUNC void pragma_nodestruct(symbol *sym);
|
SC_FUNC void pragma_nodestruct(symbol *sym);
|
||||||
|
SC_FUNC cell do_static_check(int use_warning);
|
||||||
|
|
||||||
/* function prototypes in SC2.C */
|
/* function prototypes in SC2.C */
|
||||||
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
||||||
|
@ -1802,6 +1802,13 @@ static void parse(void)
|
|||||||
case tFORWARD:
|
case tFORWARD:
|
||||||
funcstub(FALSE);
|
funcstub(FALSE);
|
||||||
break;
|
break;
|
||||||
|
case t__STATIC_ASSERT:
|
||||||
|
case t__STATIC_CHECK: {
|
||||||
|
int use_warning=(tok==t__STATIC_CHECK);
|
||||||
|
do_static_check(use_warning);
|
||||||
|
needtoken(';');
|
||||||
|
break;
|
||||||
|
} /* case */
|
||||||
case '}':
|
case '}':
|
||||||
error(54); /* unmatched closing brace */
|
error(54); /* unmatched closing brace */
|
||||||
break;
|
break;
|
||||||
@ -8530,3 +8537,96 @@ SC_FUNC void pragma_nodestruct(symbol *sym)
|
|||||||
if (sym->ident==iVARIABLE || sym->ident==iARRAY)
|
if (sym->ident==iVARIABLE || sym->ident==iARRAY)
|
||||||
sym->usage |= uNODESTRUCT;
|
sym->usage |= uNODESTRUCT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do_static_check()
|
||||||
|
* Checks compile-time assertions and triggers an error/warning.
|
||||||
|
*
|
||||||
|
* The 'use_warning' parameter is set to TRUE if warnings are to be
|
||||||
|
* used instead of errors to notify assertion failures.
|
||||||
|
*/
|
||||||
|
SC_FUNC cell do_static_check(int use_warning)
|
||||||
|
{
|
||||||
|
int already_staging,didalloc,optmsg;
|
||||||
|
int ident,index;
|
||||||
|
int bck_litidx;
|
||||||
|
int exprstartfline,exprendfline;
|
||||||
|
cell cidx,val;
|
||||||
|
char *str;
|
||||||
|
const unsigned char *exprstart,*exprend;
|
||||||
|
|
||||||
|
str=NULL;
|
||||||
|
didalloc=optmsg=FALSE;
|
||||||
|
index=0;
|
||||||
|
cidx=0;
|
||||||
|
|
||||||
|
needtoken('(');
|
||||||
|
already_staging=stgget(&index,&cidx);
|
||||||
|
if (!already_staging) {
|
||||||
|
stgset(TRUE); /* start stage-buffering */
|
||||||
|
errorset(sEXPRMARK,0);
|
||||||
|
} /* if */
|
||||||
|
exprstart=lptr;
|
||||||
|
exprstartfline=fline;
|
||||||
|
ident=expression(&val,NULL,NULL,FALSE);
|
||||||
|
if (ident!=iCONSTEXPR)
|
||||||
|
error(8); /* must be constant expression */
|
||||||
|
exprend=lptr;
|
||||||
|
exprendfline=fline;
|
||||||
|
stgdel(index,cidx); /* scratch generated code */
|
||||||
|
if (!already_staging) {
|
||||||
|
errorset(sEXPRRELEASE,0);
|
||||||
|
stgset(FALSE); /* stop stage-buffering */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
/* don't bother allocating space and copying the message
|
||||||
|
* if the expression is true */
|
||||||
|
if (val==0) {
|
||||||
|
if (exprstartfline==exprendfline) {
|
||||||
|
/* skip leading whitespaces */
|
||||||
|
while (*exprstart==' ')
|
||||||
|
exprstart++;
|
||||||
|
/* strip the trailing ',' or ')'. as well as the whitespaces */
|
||||||
|
exprend--;
|
||||||
|
if (*exprend==')' || *exprend==',') {
|
||||||
|
while (*(exprend-1)==' ')
|
||||||
|
exprend--;
|
||||||
|
} /* if */
|
||||||
|
/* copy the expression string */
|
||||||
|
str=malloc((exprend-exprstart+1)*sizeof(char));
|
||||||
|
if (str==NULL)
|
||||||
|
error(103); /* insufficient memory */
|
||||||
|
memcpy(str,exprstart,exprend-exprstart);
|
||||||
|
str[exprend-exprstart]='\0';
|
||||||
|
didalloc=TRUE;
|
||||||
|
} else {
|
||||||
|
/* Currently there's no reliable way to capture multiline expressions,
|
||||||
|
* as the lexer would only keep the contents of the line the expression
|
||||||
|
* ends at, so try to print "-epression-" instead. Not the prefect
|
||||||
|
* solution, but at least it's better than not printing anything. */
|
||||||
|
str="-expression-";
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
/* read the optional message */
|
||||||
|
if (matchtoken(',')) {
|
||||||
|
if (didalloc) {
|
||||||
|
free(str);
|
||||||
|
didalloc=FALSE;
|
||||||
|
} /* if */
|
||||||
|
optmsg=TRUE;
|
||||||
|
str=parsestringparam(val!=0,&bck_litidx);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (val==0) {
|
||||||
|
int errnum=use_warning ? 249 /* check failed */
|
||||||
|
: 110; /* assertion failed */
|
||||||
|
error(errnum,(str!=NULL) ? str : "");
|
||||||
|
if (didalloc)
|
||||||
|
free(str);
|
||||||
|
else if (optmsg && str!=NULL)
|
||||||
|
litidx=bck_litidx; /* remove the string from the literal queue */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
needtoken(')');
|
||||||
|
return !!val;
|
||||||
|
}
|
||||||
|
@ -1627,6 +1627,16 @@ static int hier2(value *lval)
|
|||||||
} /* if */
|
} /* if */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} /* case */
|
} /* case */
|
||||||
|
case t__STATIC_ASSERT:
|
||||||
|
case t__STATIC_CHECK: {
|
||||||
|
int use_warning=(tok==t__STATIC_CHECK);
|
||||||
|
clear_value(lval);
|
||||||
|
lval->ident=iCONSTEXPR;
|
||||||
|
lval->constval=do_static_check(use_warning);
|
||||||
|
lval->tag=BOOLTAG;
|
||||||
|
pc_sideeffect=TRUE;
|
||||||
|
return FALSE;
|
||||||
|
} /* case */
|
||||||
case t__EMIT:
|
case t__EMIT:
|
||||||
paranthese=matchtoken('(');
|
paranthese=matchtoken('(');
|
||||||
emit_flags |= efEXPR;
|
emit_flags |= efEXPR;
|
||||||
|
@ -206,7 +206,8 @@ static char *warnmsg[] = {
|
|||||||
/*245*/ "enum increment \"%s %d\" has no effect on zero value (symbol \"%s\")\n",
|
/*245*/ "enum increment \"%s %d\" has no effect on zero value (symbol \"%s\")\n",
|
||||||
/*246*/ "multiplication overflow in enum element declaration (symbol \"%s\")\n",
|
/*246*/ "multiplication overflow in enum element declaration (symbol \"%s\")\n",
|
||||||
/*247*/ "use of operator \"~\" on a \"bool:\" value always results in \"true\"\n",
|
/*247*/ "use of operator \"~\" on a \"bool:\" value always results in \"true\"\n",
|
||||||
/*248*/ "possible misuse of comma operator\n"
|
/*248*/ "possible misuse of comma operator\n",
|
||||||
|
/*249*/ "check failed: %s\n"
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *noticemsg[] = {
|
static char *noticemsg[] = {
|
||||||
|
@ -111,8 +111,8 @@ SC_VDEFINE char *sc_tokens[] = {
|
|||||||
"__addressof", "assert", "*begin", "break", "case", "char", "const", "continue",
|
"__addressof", "assert", "*begin", "break", "case", "char", "const", "continue",
|
||||||
"default", "defined", "do", "else", "__emit", "*end", "enum", "exit", "for",
|
"default", "defined", "do", "else", "__emit", "*end", "enum", "exit", "for",
|
||||||
"forward", "goto", "if", "__nameof", "native", "new", "operator", "__pragma",
|
"forward", "goto", "if", "__nameof", "native", "new", "operator", "__pragma",
|
||||||
"public", "return", "sizeof", "sleep", "state", "static", "stock", "switch",
|
"public", "return", "sizeof", "sleep", "state", "static", "__static_assert",
|
||||||
"tagof", "*then", "while",
|
"__static_check", "stock", "switch", "tagof", "*then", "while",
|
||||||
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
||||||
"#endscript", "#error", "#file", "#if", "#include", "#line", "#pragma",
|
"#endscript", "#error", "#file", "#if", "#include", "#line", "#pragma",
|
||||||
"#tryinclude", "#undef", "#warning",
|
"#tryinclude", "#undef", "#warning",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user