mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 04:30:10 +00:00
Add support for static_assert
Add C11's _Static_assert and static_assert macro. This is like #error, but is handled at a later stage of translation, so it is possible to check sizes of types, values of enums, etc. https://en.cppreference.com/w/c/language/_Static_assert https://port70.net/~nsz/c/c11/n1570.html#6.7.10
This commit is contained in:
parent
c72fa735b9
commit
3df6c383c0
@ -46,6 +46,12 @@ extern void __fastcall__ _afailed (const char*, unsigned);
|
||||
# define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** TODO: Guard with #if __STDC_VERSION__ >= 201112L or similar when there
|
||||
** is a C11 mode.
|
||||
*/
|
||||
#define static_assert _Static_assert
|
||||
|
||||
|
||||
|
||||
/* End of assert.h */
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "pragma.h"
|
||||
#include "preproc.h"
|
||||
#include "standard.h"
|
||||
#include "staticassert.h"
|
||||
#include "symtab.h"
|
||||
|
||||
|
||||
@ -108,6 +109,12 @@ static void Parse (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for a _Static_assert */
|
||||
if (CurTok.Tok == TOK_STATIC_ASSERT) {
|
||||
ParseStaticAssert ();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read variable defs and functions */
|
||||
ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT);
|
||||
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "pragma.h"
|
||||
#include "scanner.h"
|
||||
#include "standard.h"
|
||||
#include "staticassert.h"
|
||||
#include "symtab.h"
|
||||
#include "wrappedcall.h"
|
||||
#include "typeconv.h"
|
||||
@ -935,6 +936,13 @@ static SymEntry* ParseStructDecl (const char* Name)
|
||||
|
||||
/* Get the type of the entry */
|
||||
DeclSpec Spec;
|
||||
|
||||
/* Check for a _Static_assert */
|
||||
if (CurTok.Tok == TOK_STATIC_ASSERT) {
|
||||
ParseStaticAssert ();
|
||||
continue;
|
||||
}
|
||||
|
||||
InitDeclSpec (&Spec);
|
||||
ParseTypeSpec (&Spec, -1, T_QUAL_NONE);
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "locals.h"
|
||||
#include "stackptr.h"
|
||||
#include "standard.h"
|
||||
#include "staticassert.h"
|
||||
#include "symtab.h"
|
||||
#include "typeconv.h"
|
||||
#include "input.h"
|
||||
@ -511,6 +512,13 @@ void DeclareLocals (void)
|
||||
** declarations.
|
||||
*/
|
||||
DeclSpec Spec;
|
||||
|
||||
/* Check for a _Static_assert */
|
||||
if (CurTok.Tok == TOK_STATIC_ASSERT) {
|
||||
ParseStaticAssert ();
|
||||
continue;
|
||||
}
|
||||
|
||||
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
|
||||
if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */
|
||||
(Spec.Flags & DS_DEF_TYPE) != 0 && /* No type given */
|
||||
|
@ -86,6 +86,7 @@ static const struct Keyword {
|
||||
unsigned char Std; /* Token supported in which standards? */
|
||||
} Keywords [] = {
|
||||
{ "_Pragma", TOK_PRAGMA, TT_C89 | TT_C99 | TT_CC65 }, /* !! */
|
||||
{ "_Static_assert", TOK_STATIC_ASSERT, TT_CC65 }, /* C11 */
|
||||
{ "__AX__", TOK_AX, TT_C89 | TT_C99 | TT_CC65 },
|
||||
{ "__A__", TOK_A, TT_C89 | TT_C99 | TT_CC65 },
|
||||
{ "__EAX__", TOK_EAX, TT_C89 | TT_C99 | TT_CC65 },
|
||||
|
@ -173,6 +173,7 @@ typedef enum token_t {
|
||||
TOK_WCSCONST,
|
||||
|
||||
TOK_ATTRIBUTE,
|
||||
TOK_STATIC_ASSERT,
|
||||
TOK_FAR,
|
||||
TOK_NEAR,
|
||||
TOK_A,
|
||||
|
96
src/cc65/staticassert.c
Normal file
96
src/cc65/staticassert.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* staticassert.h */
|
||||
/* */
|
||||
/* _Static_assert handling for the cc65 C compiler */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* Copyright 2020 Google LLC */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* cc65 */
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
#include "litpool.h"
|
||||
#include "scanner.h"
|
||||
#include "staticassert.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* _Static_assert handling functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void ParseStaticAssert ()
|
||||
{
|
||||
/*
|
||||
** static_assert-declaration ::=
|
||||
** _Static_assert ( constant-expression , string-literal ) ;
|
||||
*/
|
||||
ExprDesc Expr;
|
||||
int failed;
|
||||
|
||||
/* Skip the _Static_assert token itself */
|
||||
CHECK (CurTok.Tok == TOK_STATIC_ASSERT);
|
||||
NextToken ();
|
||||
|
||||
/* We expect an opening paren */
|
||||
if (!ConsumeLParen ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse assertion condition */
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
failed = !Expr.IVal;
|
||||
|
||||
/* We expect a comma */
|
||||
if (!ConsumeComma ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* String literal */
|
||||
if (CurTok.Tok != TOK_SCONST) {
|
||||
Error ("String literal expected for static_assert message");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Issue an error including the message if the static_assert failed. */
|
||||
if (failed) {
|
||||
Error ("static_assert failed '%s'", GetLiteralStr (CurTok.SVal));
|
||||
}
|
||||
|
||||
/* Consume the string constant, now that we don't need it anymore.
|
||||
** This should never fail since we checked the token type above.
|
||||
*/
|
||||
if (!Consume (TOK_SCONST, "String literal expected")) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Closing paren and semi-colon needed */
|
||||
ConsumeRParen ();
|
||||
ConsumeSemi ();
|
||||
}
|
51
src/cc65/staticassert.h
Normal file
51
src/cc65/staticassert.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* staticassert.h */
|
||||
/* */
|
||||
/* _Static_assert handling for the cc65 C compiler */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* Copyright 2020 Google LLC */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef STATICASSERT_H
|
||||
#define STATICASSERT_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void ParseStaticAssert (void);
|
||||
/* Handle _Static_assert. These are a C11 feature. */
|
||||
|
||||
|
||||
|
||||
/* End of staticassert.h */
|
||||
|
||||
#endif
|
26
test/err/staticassert.c
Normal file
26
test/err/staticassert.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Test of failing _Static_assert.
|
||||
**/
|
||||
|
||||
|
||||
_Static_assert(0, "0 should be false.");
|
70
test/val/staticassert.c
Normal file
70
test/val/staticassert.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Tests of passing _Static_asserts.
|
||||
**/
|
||||
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
_Static_assert (1, "1 should be true.");
|
||||
_Static_assert (!0, "!0 should be true.");
|
||||
_Static_assert (1 == 1, "1 == 1 should be true.");
|
||||
_Static_assert (1 == 1L, "1 == 1L should be true.");
|
||||
_Static_assert (1 != 0, "1 != 0 should be true.");
|
||||
_Static_assert (sizeof (char) == 1, "sizeof (char) should be 1.");
|
||||
_Static_assert (sizeof (int) == 2, "sizeof (int) should be 2.");
|
||||
|
||||
/* Make sure we can also do structs. */
|
||||
struct sc { char a; };
|
||||
_Static_assert (sizeof (struct sc) == 1, "sizeof (struct sc) should be 1.");
|
||||
struct si { int a; };
|
||||
_Static_assert (sizeof (struct si) == 2, "sizeof (struct si) should be 2.");
|
||||
|
||||
/* Try enums. */
|
||||
enum { k = 1 };
|
||||
_Static_assert (k == 1, "k should be 1.");
|
||||
|
||||
/* Just test the macro version once. */
|
||||
static_assert (1, "1 should be true.");
|
||||
|
||||
/* _Static_assert can appear anywhere a declaration can. */
|
||||
void f (void)
|
||||
{
|
||||
_Static_assert (1, "1 should still be true.");
|
||||
if (1) {
|
||||
_Static_assert (1, "1 should still be true.");
|
||||
}
|
||||
}
|
||||
|
||||
/* _Static_assert can also appear in structs. */
|
||||
struct S {
|
||||
int a;
|
||||
_Static_assert (1, "1 should still be true.");
|
||||
int b;
|
||||
};
|
||||
|
||||
|
||||
int main (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user