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!
This seems more complexity than we need. How about factoring out a ParseConstantExpressionInExprEvalContext function that doesn't create a context, and then calling it from this function after creating the context?