Allow comments within _Pragma(). Fixes #2231.
This commit is contained in:
@@ -48,6 +48,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "litpool.h"
|
#include "litpool.h"
|
||||||
|
#include "preproc.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "scanstrbuf.h"
|
#include "scanstrbuf.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
@@ -866,24 +867,18 @@ static void NoteMessagePragma (const char* Message)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ParsePragmaString (void)
|
static void ParsePragmaString (StrBuf* B)
|
||||||
/* Parse the contents of _Pragma */
|
/* Parse the contents of _Pragma */
|
||||||
{
|
{
|
||||||
pragma_t Pragma;
|
pragma_t Pragma;
|
||||||
StrBuf Ident = AUTO_STRBUF_INITIALIZER;
|
StrBuf Ident = AUTO_STRBUF_INITIALIZER;
|
||||||
|
|
||||||
/* Create a string buffer from the string literal */
|
|
||||||
StrBuf B = AUTO_STRBUF_INITIALIZER;
|
|
||||||
|
|
||||||
|
|
||||||
SB_Append (&B, GetLiteralStrBuf (CurTok.SVal));
|
|
||||||
|
|
||||||
/* Skip the string token */
|
/* Skip the string token */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Get the pragma name from the string */
|
/* Get the pragma name from the string */
|
||||||
SB_SkipWhite (&B);
|
SB_SkipWhite (B);
|
||||||
if (!SB_GetSym (&B, &Ident, "-")) {
|
if (!SB_GetSym (B, &Ident, "-")) {
|
||||||
Error ("Invalid pragma");
|
Error ("Invalid pragma");
|
||||||
goto ExitPoint;
|
goto ExitPoint;
|
||||||
}
|
}
|
||||||
@@ -903,119 +898,119 @@ static void ParsePragmaString (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for an open paren */
|
/* Check for an open paren */
|
||||||
SB_SkipWhite (&B);
|
SB_SkipWhite (B);
|
||||||
if (SB_Get (&B) != '(') {
|
if (SB_Get (B) != '(') {
|
||||||
Error ("'(' expected");
|
Error ("'(' expected");
|
||||||
goto ExitPoint;
|
goto ExitPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip white space before the argument */
|
/* Skip white space before the argument */
|
||||||
SB_SkipWhite (&B);
|
SB_SkipWhite (B);
|
||||||
|
|
||||||
/* Switch for the different pragmas */
|
/* Switch for the different pragmas */
|
||||||
switch (Pragma) {
|
switch (Pragma) {
|
||||||
|
|
||||||
case PRAGMA_ALIGN:
|
case PRAGMA_ALIGN:
|
||||||
/* TODO: PES_EXPR (PES_DECL) */
|
/* TODO: PES_EXPR (PES_DECL) */
|
||||||
IntPragma (PES_STMT, Pragma, &B, &DataAlignment, 1, 4096);
|
IntPragma (PES_STMT, Pragma, B, &DataAlignment, 1, 4096);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_ALLOW_EAGER_INLINE:
|
case PRAGMA_ALLOW_EAGER_INLINE:
|
||||||
FlagPragma (PES_STMT, Pragma, &B, &EagerlyInlineFuncs);
|
FlagPragma (PES_STMT, Pragma, B, &EagerlyInlineFuncs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_BSS_NAME:
|
case PRAGMA_BSS_NAME:
|
||||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||||
SegNamePragma (PES_FUNC, PRAGMA_BSS_NAME, &B);
|
SegNamePragma (PES_FUNC, PRAGMA_BSS_NAME, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_CHARMAP:
|
case PRAGMA_CHARMAP:
|
||||||
CharMapPragma (PES_IMM, &B);
|
CharMapPragma (PES_IMM, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_CHECK_STACK:
|
case PRAGMA_CHECK_STACK:
|
||||||
/* TODO: PES_SCOPE maybe? */
|
/* TODO: PES_SCOPE maybe? */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &CheckStack);
|
FlagPragma (PES_FUNC, Pragma, B, &CheckStack);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_CODE_NAME:
|
case PRAGMA_CODE_NAME:
|
||||||
/* PES_FUNC is the only sensible option so far */
|
/* PES_FUNC is the only sensible option so far */
|
||||||
SegNamePragma (PES_FUNC, PRAGMA_CODE_NAME, &B);
|
SegNamePragma (PES_FUNC, PRAGMA_CODE_NAME, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_CODESIZE:
|
case PRAGMA_CODESIZE:
|
||||||
/* PES_EXPR would be optimization nightmare */
|
/* PES_EXPR would be optimization nightmare */
|
||||||
IntPragma (PES_STMT, Pragma, &B, &CodeSizeFactor, 10, 1000);
|
IntPragma (PES_STMT, Pragma, B, &CodeSizeFactor, 10, 1000);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_DATA_NAME:
|
case PRAGMA_DATA_NAME:
|
||||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||||
SegNamePragma (PES_FUNC, PRAGMA_DATA_NAME, &B);
|
SegNamePragma (PES_FUNC, PRAGMA_DATA_NAME, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_INLINE_STDFUNCS:
|
case PRAGMA_INLINE_STDFUNCS:
|
||||||
/* TODO: PES_EXPR maybe? */
|
/* TODO: PES_EXPR maybe? */
|
||||||
FlagPragma (PES_STMT, Pragma, &B, &InlineStdFuncs);
|
FlagPragma (PES_STMT, Pragma, B, &InlineStdFuncs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_LOCAL_STRINGS:
|
case PRAGMA_LOCAL_STRINGS:
|
||||||
/* TODO: PES_STMT or even PES_EXPR */
|
/* TODO: PES_STMT or even PES_EXPR */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &LocalStrings);
|
FlagPragma (PES_FUNC, Pragma, B, &LocalStrings);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_MESSAGE:
|
case PRAGMA_MESSAGE:
|
||||||
/* PES_IMM is the only sensible option */
|
/* PES_IMM is the only sensible option */
|
||||||
StringPragma (PES_IMM, &B, NoteMessagePragma);
|
StringPragma (PES_IMM, B, NoteMessagePragma);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_OPTIMIZE:
|
case PRAGMA_OPTIMIZE:
|
||||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||||
FlagPragma (PES_STMT, Pragma, &B, &Optimize);
|
FlagPragma (PES_STMT, Pragma, B, &Optimize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_REGVARADDR:
|
case PRAGMA_REGVARADDR:
|
||||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &AllowRegVarAddr);
|
FlagPragma (PES_FUNC, Pragma, B, &AllowRegVarAddr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_REGISTER_VARS:
|
case PRAGMA_REGISTER_VARS:
|
||||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &EnableRegVars);
|
FlagPragma (PES_FUNC, Pragma, B, &EnableRegVars);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_RODATA_NAME:
|
case PRAGMA_RODATA_NAME:
|
||||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||||
SegNamePragma (PES_FUNC, PRAGMA_RODATA_NAME, &B);
|
SegNamePragma (PES_FUNC, PRAGMA_RODATA_NAME, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_SIGNED_CHARS:
|
case PRAGMA_SIGNED_CHARS:
|
||||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &SignedChars);
|
FlagPragma (PES_FUNC, Pragma, B, &SignedChars);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_STATIC_LOCALS:
|
case PRAGMA_STATIC_LOCALS:
|
||||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &StaticLocals);
|
FlagPragma (PES_FUNC, Pragma, B, &StaticLocals);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_WRAPPED_CALL:
|
case PRAGMA_WRAPPED_CALL:
|
||||||
/* PES_IMM is the only sensible option */
|
/* PES_IMM is the only sensible option */
|
||||||
WrappedCallPragma (PES_IMM, &B);
|
WrappedCallPragma (PES_IMM, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_WARN:
|
case PRAGMA_WARN:
|
||||||
/* PES_IMM is the only sensible option */
|
/* PES_IMM is the only sensible option */
|
||||||
WarnPragma (PES_IMM, &B);
|
WarnPragma (PES_IMM, B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_WRITABLE_STRINGS:
|
case PRAGMA_WRITABLE_STRINGS:
|
||||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||||
FlagPragma (PES_FUNC, Pragma, &B, &WritableStrings);
|
FlagPragma (PES_FUNC, Pragma, B, &WritableStrings);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRAGMA_ZPSYM:
|
case PRAGMA_ZPSYM:
|
||||||
/* PES_IMM is the only sensible option */
|
/* PES_IMM is the only sensible option */
|
||||||
StringPragma (PES_IMM, &B, MakeZPSym);
|
StringPragma (PES_IMM, B, MakeZPSym);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1023,27 +1018,26 @@ static void ParsePragmaString (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Closing paren expected */
|
/* Closing paren expected */
|
||||||
SB_SkipWhite (&B);
|
SB_SkipWhite (B);
|
||||||
if (SB_Get (&B) != ')') {
|
if (SB_Get (B) != ')') {
|
||||||
Error ("')' expected");
|
Error ("')' expected");
|
||||||
goto ExitPoint;
|
goto ExitPoint;
|
||||||
}
|
}
|
||||||
SB_SkipWhite (&B);
|
SB_SkipWhite (B);
|
||||||
|
|
||||||
/* Allow an optional semicolon to be compatible with the old syntax */
|
/* Allow an optional semicolon to be compatible with the old syntax */
|
||||||
if (SB_Peek (&B) == ';') {
|
if (SB_Peek (B) == ';') {
|
||||||
SB_Skip (&B);
|
SB_Skip (B);
|
||||||
SB_SkipWhite (&B);
|
SB_SkipWhite (B);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure nothing follows */
|
/* Make sure nothing follows */
|
||||||
if (SB_Peek (&B) != '\0') {
|
if (SB_Peek (B) != '\0') {
|
||||||
Error ("Unexpected input following pragma directive");
|
Error ("Unexpected input following pragma directive");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitPoint:
|
ExitPoint:
|
||||||
/* Release the string buffers */
|
/* Release the string buffers */
|
||||||
SB_Done (&B);
|
|
||||||
SB_Done (&Ident);
|
SB_Done (&Ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1082,8 +1076,24 @@ void ConsumePragma (void)
|
|||||||
*/
|
*/
|
||||||
PragmaErrorSkip ();
|
PragmaErrorSkip ();
|
||||||
} else {
|
} else {
|
||||||
|
/* Pragmas that have the C99 _Pragma operator in the source code
|
||||||
|
** (instead of #pragma that was converted to _Pragma by the
|
||||||
|
** preprocessor) have the argument not preprocessed. We need to do
|
||||||
|
** that here, since it may contain comments. Weird but legal C. Pragmas
|
||||||
|
** that were converted from #pragma are already preprocessed but doing
|
||||||
|
** it twice won't harm.
|
||||||
|
*/
|
||||||
|
StrBuf In = AUTO_STRBUF_INITIALIZER;
|
||||||
|
StrBuf Out = AUTO_STRBUF_INITIALIZER;
|
||||||
|
SB_Append (&In, GetLiteralStrBuf (CurTok.SVal));
|
||||||
|
TranslationPhase3 (&In, &Out);
|
||||||
|
SB_Done (&In);
|
||||||
|
|
||||||
/* Parse the pragma */
|
/* Parse the pragma */
|
||||||
ParsePragmaString ();
|
ParsePragmaString (&Out);
|
||||||
|
|
||||||
|
/* Free the string buffer */
|
||||||
|
SB_Done (&Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
--InPragmaParser;
|
--InPragmaParser;
|
||||||
|
|||||||
@@ -157,11 +157,6 @@ struct HiddenMacro {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void TranslationPhase3 (StrBuf* Source, StrBuf* Target);
|
|
||||||
/* Mimic Translation Phase 3. Handle old and new style comments. Collapse
|
|
||||||
** non-newline whitespace sequences.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFlags);
|
static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFlags);
|
||||||
/* Preprocess a single line. Handle specified tokens and operators, remove
|
/* Preprocess a single line. Handle specified tokens and operators, remove
|
||||||
** whitespace and comments, then do macro replacement.
|
** whitespace and comments, then do macro replacement.
|
||||||
@@ -3338,7 +3333,22 @@ void HandleSpecialMacro (Macro* M, const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void TranslationPhase3 (StrBuf* Source, StrBuf* Target)
|
static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFlags)
|
||||||
|
/* Preprocess a single line. Handle specified tokens and operators, remove
|
||||||
|
** whitespace and comments, then do macro replacement.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
MacroExp E;
|
||||||
|
|
||||||
|
SkipWhitespace (0);
|
||||||
|
InitMacroExp (&E);
|
||||||
|
ReplaceMacros (Source, Target, &E, ModeFlags | MSM_IN_DIRECTIVE);
|
||||||
|
DoneMacroExp (&E);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void TranslationPhase3 (StrBuf* Source, StrBuf* Target)
|
||||||
/* Mimic Translation Phase 3. Handle old and new style comments. Collapse
|
/* Mimic Translation Phase 3. Handle old and new style comments. Collapse
|
||||||
** non-newline whitespace sequences.
|
** non-newline whitespace sequences.
|
||||||
*/
|
*/
|
||||||
@@ -3384,21 +3394,6 @@ static void TranslationPhase3 (StrBuf* Source, StrBuf* Target)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFlags)
|
|
||||||
/* Preprocess a single line. Handle specified tokens and operators, remove
|
|
||||||
** whitespace and comments, then do macro replacement.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
MacroExp E;
|
|
||||||
|
|
||||||
SkipWhitespace (0);
|
|
||||||
InitMacroExp (&E);
|
|
||||||
ReplaceMacros (Source, Target, &E, ModeFlags | MSM_IN_DIRECTIVE);
|
|
||||||
DoneMacroExp (&E);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Preprocess (void)
|
void Preprocess (void)
|
||||||
/* Preprocess lines count of which is affected by directives */
|
/* Preprocess lines count of which is affected by directives */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ struct IFile;
|
|||||||
void HandleSpecialMacro (Macro* M, const char* Name);
|
void HandleSpecialMacro (Macro* M, const char* Name);
|
||||||
/* Handle special "magic" macros that may change */
|
/* Handle special "magic" macros that may change */
|
||||||
|
|
||||||
|
void TranslationPhase3 (StrBuf* Source, StrBuf* Target);
|
||||||
|
/* Mimic Translation Phase 3. Handle old and new style comments. Collapse
|
||||||
|
** non-newline whitespace sequences.
|
||||||
|
*/
|
||||||
|
|
||||||
void Preprocess (void);
|
void Preprocess (void);
|
||||||
/* Preprocess a line */
|
/* Preprocess a line */
|
||||||
|
|
||||||
|
|||||||
10
test/val/bug2231.c
Normal file
10
test/val/bug2231.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
_Pragma("message/*Comment1*/ ( /*Comment2*/\"test message\" /*Comment3*/)")
|
||||||
|
/* We have no pragma without parenthesis but if there would be one, the
|
||||||
|
** following should also work:
|
||||||
|
*/
|
||||||
|
/* _Pragma("once// Comment") */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user