Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -1198,42 +1198,73 @@ // 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. - if (isCXXTypeId(TypeIdAsTemplateArgument)) { - SourceLocation Loc = Tok.getLocation(); - TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr, - Declarator::TemplateTypeArgContext); - if (TypeArg.isInvalid()) - return ParsedTemplateArgument(); - - return ParsedTemplateArgument(ParsedTemplateArgument::Type, - TypeArg.get().getAsOpaquePtr(), - Loc); - } - + // Therefore, we initially try to parse a type-id. + { + EnterExpressionEvaluationContext EnterConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + if (isCXXTypeId(TypeIdAsTemplateArgument)) { + SourceLocation Loc = Tok.getLocation(); + TypeResult TypeArg = + ParseTypeName(/*Range=*/nullptr, Declarator::TemplateTypeArgContext); + if (TypeArg.isInvalid()) + return ParsedTemplateArgument(); + + return ParsedTemplateArgument(ParsedTemplateArgument::Type, + TypeArg.get().getAsOpaquePtr(), Loc); + } else { + // If we disambiguated as an expression that we identified as potentially + // not being odr-used (consistent with a template argument context), and + // annotated our token as that expression, then remove it from the + // MaybeODRUsedExprs so that it doesn't trigger a false error, since it + // would otherwise have been removed when completing processing of a + // constant expression. + if (Actions.MaybeODRUseExprs.size()) { + assert(Actions.MaybeODRUseExprs.size() == 1 && + "we should only need to parse one expression to determine an " + "error or typeid"); + assert(Tok.getKind() == tok::annot_primary_expr && + getExprAnnotation(Tok).get() == + *Actions.MaybeODRUseExprs.begin() && + "The expression (DeclRefExpr or MemExpr) stored within " + "MaybeODRUseExprs for later checking whether we perform an " + "lvalue-to-rvalue conversion before determining odr-use must be " + "the same as the annotated token during ambiguity resolution"); + // We clear this state, since this lingering partially processed + // expression should not trigger an error now and we don't need to save + // it for later since we can be certain that this expression would + // eventually have been removed during ActOnConstantExpression called + // from ParseConstantExpression when parsing the non-type template + // argument below. Eitherway, the appropriate checking for an + // appropriate constant-expression that matches the + // non-type-template-parameter occurs later in CheckTemplateArgument. + Actions.MaybeODRUseExprs.clear(); + } + } + } // End ExpressionEvaluationContext + // Try to parse a template template argument. { TentativeParsingAction TPA(*this); - ParsedTemplateArgument TemplateTemplateArgument - = ParseTemplateTemplateArgument(); + ParsedTemplateArgument TemplateTemplateArgument = + ParseTemplateTemplateArgument(); if (!TemplateTemplateArgument.isInvalid()) { TPA.Commit(); return TemplateTemplateArgument; } - + // Revert this tentative parse to parse a non-type template argument. TPA.Revert(); } - - // Parse a non-type template argument. + + // Parse a non-type template argument. SourceLocation Loc = Tok.getLocation(); ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast); if (ExprArg.isInvalid() || !ExprArg.get()) return ParsedTemplateArgument(); - return ParsedTemplateArgument(ParsedTemplateArgument::NonType, - ExprArg.get(), Loc); + return ParsedTemplateArgument(ParsedTemplateArgument::NonType, ExprArg.get(), + Loc); } /// \brief Determine whether the current tokens can only be parsed as a @@ -1274,16 +1305,16 @@ /// 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 { ParsedTemplateArgument Arg = ParseTemplateArgument(); SourceLocation EllipsisLoc; - if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { + // FIXME: Do we need need to enter a constant evaluation context here? Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc); + } if (Arg.isInvalid()) { SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);