1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

Fixed the bug that redefined macros could co-exist but not all be undefined with a single #undef.

This commit is contained in:
acqn 2022-08-06 18:21:42 +08:00
parent b93f9fbba4
commit ae811baaf1
2 changed files with 155 additions and 126 deletions

View File

@ -809,131 +809,6 @@ static void ExpandMacro (StrBuf* Target, Macro* M, int MultiLine)
static void DefineMacro (void)
/* Handle a macro definition. */
{
ident Ident;
Macro* M;
Macro* Existing;
int C89;
/* Read the macro name */
SkipWhitespace (0);
if (!MacName (Ident)) {
return;
}
/* Remember if we're in C89 mode */
C89 = (IS_Get (&Standard) == STD_C89);
/* Get an existing macro definition with this name */
Existing = FindMacro (Ident);
/* Create a new macro definition */
M = NewMacro (Ident);
/* Check if this is a function like macro */
if (CurC == '(') {
/* Skip the left paren */
NextChar ();
/* Set the marker that this is a function like macro */
M->ArgCount = 0;
/* Read the formal parameter list */
while (1) {
/* Skip white space and check for end of parameter list */
SkipWhitespace (0);
if (CurC == ')') {
break;
}
/* The next token must be either an identifier, or - if not in
** C89 mode - the ellipsis.
*/
if (!C89 && CurC == '.') {
/* Ellipsis */
NextChar ();
if (CurC != '.' || NextC != '.') {
PPError ("'...' expected");
ClearLine ();
return;
}
NextChar ();
NextChar ();
/* Remember that the macro is variadic and use __VA_ARGS__ as
** the argument name.
*/
AddMacroArg (M, "__VA_ARGS__");
M->Variadic = 1;
} else {
/* Must be macro argument name */
if (MacName (Ident) == 0) {
return;
}
/* __VA_ARGS__ is only allowed in C89 mode */
if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) {
PPWarning ("'__VA_ARGS__' can only appear in the expansion "
"of a C99 variadic macro");
}
/* Add the macro argument */
AddMacroArg (M, Ident);
}
/* If we had an ellipsis, or the next char is not a comma, we've
** reached the end of the macro argument list.
*/
SkipWhitespace (0);
if (M->Variadic || CurC != ',') {
break;
}
NextChar ();
}
/* Check for a right paren and eat it if we find one */
if (CurC != ')') {
PPError ("')' expected");
ClearLine ();
return;
}
NextChar ();
}
/* Skip whitespace before the macro replacement */
SkipWhitespace (0);
/* Insert the macro into the macro table and allocate the ActualArgs array */
InsertMacro (M);
/* Remove whitespace and comments from the line, store the preprocessed
** line into the macro replacement buffer.
*/
TranslationPhase3 (Line, &M->Replacement);
/* Remove whitespace from the end of the line */
while (IsSpace (SB_LookAtLast (&M->Replacement))) {
SB_Drop (&M->Replacement, 1);
}
#if 0
printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement));
#endif
/* If we have an existing macro, check if the redefinition is identical.
** Print a diagnostic if not.
*/
if (Existing && MacroCmp (M, Existing) != 0) {
PPError ("Macro redefinition is not identical");
}
}
/*****************************************************************************/
/* Preprocessing */
/*****************************************************************************/
@ -1161,6 +1036,135 @@ static void MacroReplacement (StrBuf* Source, StrBuf* Target, int MultiLine)
static void DoDefine (void)
/* Process #define directive */
{
ident Ident;
Macro* M;
Macro* Existing;
int C89;
/* Read the macro name */
SkipWhitespace (0);
if (!MacName (Ident)) {
return;
}
/* Remember if we're in C89 mode */
C89 = (IS_Get (&Standard) == STD_C89);
/* Create a new macro definition */
M = NewMacro (Ident);
/* Check if this is a function like macro */
if (CurC == '(') {
/* Skip the left paren */
NextChar ();
/* Set the marker that this is a function like macro */
M->ArgCount = 0;
/* Read the formal parameter list */
while (1) {
/* Skip white space and check for end of parameter list */
SkipWhitespace (0);
if (CurC == ')') {
break;
}
/* The next token must be either an identifier, or - if not in
** C89 mode - the ellipsis.
*/
if (!C89 && CurC == '.') {
/* Ellipsis */
NextChar ();
if (CurC != '.' || NextC != '.') {
PPError ("'...' expected");
ClearLine ();
return;
}
NextChar ();
NextChar ();
/* Remember that the macro is variadic and use __VA_ARGS__ as
** the argument name.
*/
AddMacroArg (M, "__VA_ARGS__");
M->Variadic = 1;
} else {
/* Must be macro argument name */
if (MacName (Ident) == 0) {
return;
}
/* __VA_ARGS__ is only allowed in post-C89 mode */
if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) {
PPWarning ("'__VA_ARGS__' can only appear in the expansion "
"of a C99 variadic macro");
}
/* Add the macro argument */
AddMacroArg (M, Ident);
}
/* If we had an ellipsis, or the next char is not a comma, we've
** reached the end of the macro argument list.
*/
SkipWhitespace (0);
if (M->Variadic || CurC != ',') {
break;
}
NextChar ();
}
/* Check for a right paren and eat it if we find one */
if (CurC != ')') {
PPError ("')' expected");
ClearLine ();
return;
}
NextChar ();
}
/* Skip whitespace before the macro replacement */
SkipWhitespace (0);
/* Remove whitespace and comments from the line, store the preprocessed
** line into the macro replacement buffer.
*/
TranslationPhase3 (Line, &M->Replacement);
/* Remove whitespace from the end of the line */
while (IsSpace (SB_LookAtLast (&M->Replacement))) {
SB_Drop (&M->Replacement, 1);
}
#if 0
printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement));
#endif
/* Get an existing macro definition with this name */
Existing = FindMacro (M->Name);
/* If we have an existing macro, check if the redefinition is identical.
** Print a diagnostic if not.
*/
if (Existing != 0) {
if (MacroCmp (M, Existing) != 0) {
PPError ("Macro redefinition is not identical");
}
/* Undefine the existing macro anyways */
UndefineMacro (Existing->Name);
}
/* Insert the new macro into the macro table */
InsertMacro (M);
}
static int PushIf (int Skip, int Invert, int Cond)
/* Push a new if level onto the if stack */
{
@ -1443,7 +1447,7 @@ static int ParseDirectives (int InArgList)
case PP_DEFINE:
if (!PPSkip) {
DefineMacro ();
DoDefine ();
}
break;

25
test/val/bug1822-pptest.c Normal file
View File

@ -0,0 +1,25 @@
/* Bug #1822 - Redefined macros failed to be all undefined with a single #undef */
#undef F
#undef F
#define F 1
#define F 1
#undef F
#if defined F
#error #undef F fails!
#endif
#define F 0
#include <stdio.h>
int main(void)
{
if (F != 0)
{
printf("failed: F = %d\n", F);
}
return F;
}