diff options
| -rw-r--r-- | src/preprocess.c | 51 | ||||
| -rw-r--r-- | tests/include_stdc.sh | 3 | ||||
| -rw-r--r-- | tests/test_macro_operators.sh | 16 |
3 files changed, 68 insertions, 2 deletions
diff --git a/src/preprocess.c b/src/preprocess.c index 7f635b8..9ec582a 100644 --- a/src/preprocess.c +++ b/src/preprocess.c @@ -881,6 +881,27 @@ MacroExpansionContext* macroexpansioncontext_new() { return ctx; } +static int expand_macro(Preprocessor* pp, bool skip_newline, MacroExpansionContext* ctx); + +static void expand_macro_arg(Preprocessor* pp, MacroArg* arg, bool skip_newline, MacroExpansionContext* ctx) { + tokens_push_new(&arg->tokens)->kind = TokenKind_eof; + + Preprocessor* pp2 = preprocessor_new(&arg->tokens, pp->include_depth, pp->macros, pp->included_files); + + size_t arg_token_count = arg->tokens.len; + size_t processed_token_count = 0; + while (processed_token_count < arg_token_count) { + if (peek_pp_token(pp2)->kind == TokenKind_ident) { + processed_token_count += expand_macro(pp2, skip_newline, ctx); + } else { + next_pp_token(pp2); + processed_token_count += 1; + } + } + + tokens_pop(&arg->tokens); +} + static int expand_macro(Preprocessor* pp, bool skip_newline, MacroExpansionContext* ctx) { if (ctx == NULL) { ctx = macroexpansioncontext_new(); @@ -888,6 +909,7 @@ static int expand_macro(Preprocessor* pp, bool skip_newline, MacroExpansionConte int macro_name_pos = pp->pos; Token* macro_name = peek_pp_token(pp); + const char* macro_name_str = macro_name->value.string; // Supress expansion if the macro has already been expanded. for (size_t i = 0; i < ctx->already_expanded.len; ++i) { @@ -903,8 +925,6 @@ static int expand_macro(Preprocessor* pp, bool skip_newline, MacroExpansionConte return 1; } - strings_push(&ctx->already_expanded, macro_name->value.string); - SourceLocation original_loc = macro_name->loc; size_t token_count_before_expansion; size_t token_count_after_expansion; @@ -915,6 +935,32 @@ static int expand_macro(Preprocessor* pp, bool skip_newline, MacroExpansionConte token_count_before_expansion = pp->pos - macro_name_pos; replace_pp_tokens(pp, macro_name_pos, pp->pos, ¯o->replacements); + bool* no_expand = calloc(macro->parameters.len, sizeof(bool)); + for (size_t i = 0; i < macro->replacements.len; ++i) { + if (i == 0 || i == macro->replacements.len - 1) + continue; + if (macro->replacements.data[i].kind == TokenKind_hashhash) { + Token* lhs = ¯o->replacements.data[i - 1]; + Token* rhs = ¯o->replacements.data[i + 1]; + int param1 = macro_find_param(macro, lhs); + int param2 = macro_find_param(macro, rhs); + if (param1 != -1) { + no_expand[param1] = true; + } + if (param2 != -1) { + no_expand[param2] = true; + } + } + } + + // Argument expansion + for (size_t i = 0; i < args->len; ++i) { + if (no_expand[i]) + continue; + MacroArg* arg = &args->data[i]; + expand_macro_arg(pp, arg, skip_newline, ctx); + } + // Parameter substitution size_t token_count = 0; size_t offset = 0; @@ -995,6 +1041,7 @@ static int expand_macro(Preprocessor* pp, bool skip_newline, MacroExpansionConte } // Recursive expansion. + strings_push(&ctx->already_expanded, macro_name_str); pp->pos = macro_name_pos; size_t processed_token_count = 0; while (processed_token_count < token_count_after_expansion) { diff --git a/tests/include_stdc.sh b/tests/include_stdc.sh index 7357bc9..deee597 100644 --- a/tests/include_stdc.sh +++ b/tests/include_stdc.sh @@ -3,6 +3,7 @@ EOF test_diff <<'EOF' #include <assert.h> +#include <ctype.h> #include <errno.h> #include <limits.h> #include <locale.h> @@ -11,6 +12,8 @@ test_diff <<'EOF' #include <stddef.h> #include <stdint.h> #include <stdio.h> +// #include <stdlib.h> +// #include <string.h> #include <time.h> #include <uchar.h> diff --git a/tests/test_macro_operators.sh b/tests/test_macro_operators.sh index daf8f47..a77d3ca 100644 --- a/tests/test_macro_operators.sh +++ b/tests/test_macro_operators.sh @@ -41,3 +41,19 @@ int main() { } EOF +cat <<'EOF' > expected +123 +EOF +test_diff <<'EOF' +int printf(const char*, ...); + +#define F(x) CHECK(G(x)) +#define G(x) CHECK(H(x)) +#define CHECK(x) x + +int H(int n) { return n; } + +int main() { + printf("%d\n", F(123)); +} +EOF |
