Curious to know if there's language that differentiate between procedure (function with side-effect) and pure function at the syntax level.
The SPARK subset of Ada enforces purity of functions at compile time.
SPARK also allows partial purity, i.e. you can declare that a procedure has side effects, but only in the sense that it uses the wall clock as an input, or only in the sense that it writes to a global variable. You can specify in some detail exactly which side effects are allowed to happen in a procedure.
__attribute__ ((pure))
__attribute__ ((const))
The 'pure' attribute imposes similar but looser restrictions on a function's definition than the 'const' attribute: 'pure' allows the function to read any non-volatile memory, even if it changes in between successive invocations of the function.