Master the fundamental concepts of semantic analysis through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksBlock scope, function scope, and file scope determine which declaration a name refers to. Clang tracks Scope objects; Java bytecode carries scope in debug tables. Shadowing (inner x hides outer x) is legal in C but dead outer bindings are often flagged as warnings.
When an inner block declares x while outer x exists, inner uses bind to inner x. The outer x is shadowed inside the block. If inner x is never used, compilers like GCC emit -Wunused-variable.
cLoading…
{, pop on }Production compilers embed this step inside a longer pipeline. GCC flows through cpp, cc1, assembly, and ld; Clang uses the driver, Sema, LLVM IR passes, and a target backend. LLVM bitcode, JVM bytecode, and WASM are other familiar IRs at the same layer. The exercise isolates one pass so you can test it alone before chaining it to the next stage.
You will implement scope analysis that detects variable shadowing and unused declarations. This exercise requires tracking nested scopes and reporting when inner names hide outer names or when variables are never used.
Walk a block-structured program with a stack of scopes and report three classic scope problems: shadowed variables, redeclarations, and unreachable code.
One statement per line (blank lines ignored; leading spaces are only indentation):
| Line | Meaning |
|---|---|
int NAME; / int NAME = EXPR; | declaration (also char, float) |
NAME = EXPR; | assignment |
return EXPR; / return; | return |
break; | break |
{ | open a plain block |
if (EXPR) { / while (EXPR) { | open a block guarded by a condition |
} | close the innermost block |
Everything outside any block is the global scope.
line L: error: redeclaration of 'NAME' (first declared on line K)line L: warning: 'NAME' shadows declaration on line K (K = the nearest enclosing declaration)return or break in that same block is dead. Report only the first dead statement of each block, once:
line L: warning: unreachable code after return on line K (or after break).
A dead statement may itself be a declaration or a block opener: it still counts as the first dead statement, and it is still checked for rules 1 and 2. A } is not a statement. A return inside an inner block does not make the code after that inner block dead.Messages print in line order (at most one per line in the tests). Finish with warnings=W errors=E.
Input:
cLoading…
Output:
cLoading…
}; each scope maps names to their declaration line.Hidden tests cover returns inside if blocks (code after them is live), break in loops, dead block openers, several levels of shadowing, and a program with no problems.