summaryrefslogtreecommitdiffstats
path: root/lib/Parse/ParseExpr.cpp
diff options
context:
space:
mode:
authorFaisal Vali <faisalv@yahoo.com>2017-05-20 19:58:04 +0000
committerFaisal Vali <faisalv@yahoo.com>2017-05-20 19:58:04 +0000
commitef421cdb4447e67530bab05b37e14e08d4661974 (patch)
treeb18b7144a421a8d5057e6c5b98fc169753228b15 /lib/Parse/ParseExpr.cpp
parent5bc2be3c8e2c5782d9d795a2579f315159e0c749 (diff)
Fix PR25627: constant expressions being odr-used in template arguments.
This patch ensures that clang processes the expression-nodes that are generated when disambiguating between types and expressions within template arguments as constant-expressions by installing the ConstantEvaluated ExpressionEvaluationContext just before attempting the disambiguation - and then making sure that Context carries through into ParseConstantExpression (by refactoring it out into a function that does not create its own EvaluationContext: ParseConstantExpressionInExprEvalContext) Note, prior to this patch, trunk would correctly disambiguate and identify the expression as an expression - and while it would annotate the token with the expression - it would fail to complete the odr-use processing (specifically, failing to trigger Sema::UpdateMarkingForLValueToRValue as is done for all Constant Expressions, which would remove it from being considered odr-used). By installing the ConstantExpression Evaluation Context prior to disambiguation, and making sure it carries though, we ensure correct processing of the expression-node. For e.g: template<int> struct X { }; void f() { const int N = 10; X<N> x; // should be OK. [] { return X<N>{}; }; // Should be OK - no capture - but clang errors! } See a related bug: https://bugs.llvm.org//show_bug.cgi?id=25627 In summary (and reiteration), the fix is as follows: - Remove the EnteredConstantEvaluatedContext action from ParseTemplateArgumentList (relying on ParseTemplateArgument getting it right) - Add the EnteredConstantEvaluatedContext action just prior to undergoing the disambiguating parse, and if the parse succeeds for an expression, carry the context though into a refactored version of ParseConstantExpression that does not create its own ExpressionEvaluationContext. See https://reviews.llvm.org/D31588 for additional context regarding some of the more fragile and complicated approaches attempted, and Richard's feedback that eventually shaped the simpler and more robust rendition that is being committed. Thanks Richard! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303492 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
-rw-r--r--lib/Parse/ParseExpr.cpp15
1 files changed, 11 insertions, 4 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index bcdc72df30..c739a50f0b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -192,6 +192,16 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
return ParseRHSOfBinaryExpression(R, prec::Assignment);
}
+ExprResult
+Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) {
+ assert(Actions.ExprEvalContexts.back().Context ==
+ Sema::ExpressionEvaluationContext::ConstantEvaluated &&
+ "Call this function only if your ExpressionEvaluationContext is "
+ "already ConstantEvaluated");
+ ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
+ ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ return Actions.ActOnConstantExpression(Res);
+}
ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
// C++03 [basic.def.odr]p2:
@@ -200,10 +210,7 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
// C++98 and C++11 have no such rule, but this is only a defect in C++98.
EnterExpressionEvaluationContext ConstantEvaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
-
- ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
- ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
- return Actions.ActOnConstantExpression(Res);
+ return ParseConstantExpressionInExprEvalContext(isTypeCast);
}
/// \brief Parse a constraint-expression.