This patch ensures that clang processes the expression-nodes that are generated when disambiguating between types and expressions within template arguments, as if they were truly constant-expressions. Currently, trunk correctly disambiguates, and identifies the expression as an expression - and while it annotates the token with the expression - it fails to complete the odr-use processing (specifically, failing to trigger Sema::UpdateMarkingForLValueToRValue as is done so for all Constant Expressions, which removes it from being considered odr-used).
For e.g:
template<int> struct X { };
void f() {
const int N = 10; X<N> x; // should be OK. [] { return X<N>{}; }; // also OK - no capture.
}
See a related bug: https://bugs.llvm.org//show_bug.cgi?id=25627
The fix is as follows:
- Remove the EnteredConstantEvaluatedContext action from ParseTemplateArgumentList (relying that ParseTemplateArgument will get it right)
- Add the EnteredConstantEvaluatedContext action just prior to undergoing the disambiguating parse, and if the parse succeeds for an expression, make sure it doesn't linger within MaybeODRUsedExprs by clearing it (while asserting that it only contains the offending expression)
I need to add some tests... and fix one regression.
Does the approach look sound?
Thanks!
Please add a comment here, something like:
isCXXTypeId might look up and annotate an identifier as an id-expression during disambiguation, so enter the appropriate context for a constant expression template argument before trying to disambiguate.