Skip to content

Fix Trac 6028: normalize SDCC assembly before preprocessing - #8892

Open
KiritoYG wants to merge 1 commit into
cppcheck-opensource:mainfrom
KiritoYG:codex/preprocess-sdcc-asm
Open

KiritoYG wants to merge 1 commit into
cppcheck-opensource:mainfrom
KiritoYG:codex/preprocess-sdcc-asm

Conversation

@KiritoYG

Copy link
Copy Markdown

Addresses the remaining SDCC examples in Trac 6028. @dptr operands currently cause a syntax error, and #(s_XINIT >> 8) is altered during preprocessing before the late assembler simplifier runs, leaving an unmatched ).

Normalize complete literal __asm / __endasm regions in the raw preprocessor tokens, including newly loaded headers. Preserve an opaque asm() analysis barrier, exactly one terminator and the locations of surrounding C code. Leave ambiguous/missing/nested regions, real preprocessing directives, macro definitions and other assembler dialects on the existing path. The existing pragma-asm handling is unchanged.

Add seven preprocessor test methods covering operands, empty/adjacent blocks, comments, missing/nested markers, other dialects, configurations and unbraced control flow. Two CLI regressions cover the main-file and included-header paths and verify that a real division-by-zero diagnostic after the block remains at its original line.

Validation:

  • The untouched base reproduces the remaining @ and #( failures; 18 original/patched CLI comparisons pass, including outside-C diagnostic and GNU/MS/macro controls.
  • Windows Clang/MinGW: 5,301 native tests, 351 existing TODOs, zero test failures; both new CLI tests pass.
  • Independent Linux GCC 11.4 verification of the exact source: warnings-as-errors build; 5,363 native tests, 360 existing TODOs, zero failures; both CLI tests pass. The helper branch adds only its verification workflow.
  • Uncrustify 0.80.1, Python lint and git diff --check pass.

One earlier Windows full-suite attempt exited with 0xc0000005 while displaying TestType::checkTooBigShift_Unix32; the full rerun above passed. The recorded fault offset resolves to the unchanged Token::Match. A bounded debugger run did not reproduce that failure but was stopped after becoming slow in TestValueFlow::valueFlowHang; its outcome is inconclusive. No root cause or baseline attribution is claimed.

This is a bounded fix for the demonstrated literal marker-delimited blocks. It does not repair initial lexer errors, macro-generated markers, or ARM assembler-function syntax.

Please assign Trac 6028 to KiritoYG for this patch and confirm whether this remaining-defect fix qualifies under the published USD 10 bounty bracket. After qualifying closure, I can use the documented bounty-request process; please also confirm the available settlement channel.

Comment thread lib/preprocessor.cpp
Comment on lines +1182 to +1185
// Preserve an asm statement as an analysis barrier, including for empty
// blocks. Hide assembler # operands before simplecpp stringifies them.
std::unique_ptr<simplecpp::Token> open(new simplecpp::Token("(", start->location));
std::unique_ptr<simplecpp::Token> close(new simplecpp::Token(")", start->location));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI review. Take it with a grain of salt and feel free to reject it by resolving the comment.

I built the PR and compared it with main. Other asm forms are unchanged: __asm("..."), __asm volatile(...), MS __asm { ... }, one-line __asm nop __endasm;, and int x __asm("sym");. Unbraced if/do bodies with a block still parse. As a bonus, a { inside an asm ; comment no longer gives a syntax error.

One behavior change I noticed: the assembler text is now dropped. For

void f(void) {
    __asm
        mov ax,bx
    __endasm;
}

main produces asm ( "mov ax , bx" ) ; (from Tokenizer::simplifyAsm(), see testtokenize.cpp around line 1191). With this PR, the --debug output and the dump file show asm ( "" ) ;. I could not find any checker or addon that reads the asm string, and #pragma asm already produces an empty asm ( ), so this may be fine. But it means the __endasm branch in Tokenizer::simplifyAsm() is now effectively dead for preprocessed input. Is that intended? If so, maybe remove or document that branch. Otherwise, maybe keep the text here by turning the removed tokens into a string literal between ( and )?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants