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:
Jesse Rosenstock
2020-07-26 22:16:47 +02:00
committed by Oliver Schmidt
parent c72fa735b9
commit 3df6c383c0
10 changed files with 274 additions and 0 deletions

View File

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

View File

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

View File

@@ -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 */

View File

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

View File

@@ -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
View 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
View 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