Consider the following code:
void foo (void) {} void (*bar)(void) = foo;
And the corresponding AST:
|-FunctionDecl 0x561e9cf12728 <x.c:14:1, col:18> col:6 used foo 'void (void)' | `-CompoundStmt 0x561e9cf12818 <col:17, col:18> `-VarDecl 0x561e9cf12958 <line:15:1, col:21> col:8 bar 'void (*)(void)' cinit `-ImplicitCastExpr 0x561e9cf129e0 <col:21> 'void (*)(void)' <FunctionToPointerDecay> `-DeclRefExpr 0x561e9cf129c0 <col:21> 'void (void)' Function 0x561e9cf12728 'foo' 'void (void)'
The ImplicitCastExpr of FunctionToPointerDecay is obviously const.
Lookup the corresponding llvm::Function in the Module by name.
I think I'd prefer to continue treating an undecayed function as an "lvalue", to keep things straightforward. To that end, I'd prefer a separate "ConstLValueExprEmitter", or something like that, so ConstExprEmitter only visits rvalues.
The new emitter should reuse code from ConstLValueExprEmitter where possible.