summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseExpr.cpp15
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp14
2 files changed, 20 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index bcdc72df305..c739a50f0b3 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/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.
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 28ae113a511..a919d870810 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1186,7 +1186,13 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
// expression is resolved to a type-id, regardless of the form of
// the corresponding template-parameter.
//
- // Therefore, we initially try to parse a type-id.
+ // Therefore, we initially try to parse a type-id - and 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.
+
+ EnterExpressionEvaluationContext EnterConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
SourceLocation Loc = Tok.getLocation();
TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr,
@@ -1216,7 +1222,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
// Parse a non-type template argument.
SourceLocation Loc = Tok.getLocation();
- ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast);
+ ExprResult ExprArg = ParseConstantExpressionInExprEvalContext(MaybeTypeCast);
if (ExprArg.isInvalid() || !ExprArg.get())
return ParsedTemplateArgument();
@@ -1262,9 +1268,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
/// template-argument-list ',' template-argument
bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
- // Template argument lists are constant-evaluation contexts.
- EnterExpressionEvaluationContext EvalContext(
- Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
ColonProtectionRAIIObject ColonProtection(*this, false);
do {
OpenPOWER on IntegriCloud