diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index ad66335138a42..aeacd0dc765ef 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -601,6 +601,13 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { assert(Ctx.getLangOpts().CPlusPlus && "This is only relevant for C++."); + + // For binary operators which are unknown due to type dependence, the + // convention is to classify them as a prvalue. This does not matter much, but + // it needs to agree with how they are created. + if (E->getType() == Ctx.DependentTy) + return Cl::CL_PRValue; + // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand. // Except we override this for writes to ObjC properties. if (E->isAssignmentOp()) diff --git a/clang/test/SemaTemplate/temp_arg_template.cpp b/clang/test/SemaTemplate/temp_arg_template.cpp index 431e19741ece9..c9576e2057e53 100644 --- a/clang/test/SemaTemplate/temp_arg_template.cpp +++ b/clang/test/SemaTemplate/temp_arg_template.cpp @@ -149,6 +149,12 @@ namespace CheckDependentNonTypeParamTypes { }; // FIXME: This should be rejected, as there are no valid instantiations for E::F template struct E; + +#if __cplusplus >= 201703L + template class TT, class V> struct G { + using type = TT<((void)0, V::value)>; + }; +#endif } namespace PR32185 {