mizvekov updated this revision to Diff 330493. mizvekov added a comment. lint
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98160/new/ https://reviews.llvm.org/D98160 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaType.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp
Index: clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp @@ -79,19 +79,23 @@ template<typename T> constexpr bool is_same_v<T, T> = true; +template<typename T> struct remove_reference { using type = T; }; +template<typename T> struct remove_reference<T&> { using type = T; }; + template<typename T, typename U> concept Same = is_same_v<T, U>; template<typename T> -concept Large = sizeof(T) >= 4; // expected-note{{because 'sizeof(short) >= 4' (2 >= 4) evaluated to false}} +concept Large = sizeof(typename remove_reference<T>::type) >= 4; +// expected-note@-1{{because 'sizeof(typename remove_reference<short &>::type) >= 4' (2 >= 4) evaluated to false}} -template<typename T> requires requires (T t) { { t } -> Large; } // expected-note{{because 'decltype(t)' (aka 'short') does not satisfy 'Large':}} +template<typename T> requires requires (T t) { { t } -> Large; } // expected-note{{because 'decltype((t))' (aka 'short &') does not satisfy 'Large':}} struct r7 {}; using r7i1 = r7<int>; using r7i2 = r7<short>; // expected-error{{constraints not satisfied for class template 'r7' [with T = short]}} -template<typename T> requires requires (T t) { { t } -> Same<T>; } +template<typename T> requires requires (T t) { { t } -> Same<T&>; } struct r8 {}; using r8i1 = r8<int>; @@ -99,7 +103,8 @@ // Substitution failure in type constraint -template<typename T> requires requires (T t) { { t } -> Same<typename T::type>; } // expected-note{{because 'Same<expr-type, typename T::type>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} +template<typename T> requires requires (T t) { { t } -> Same<typename T::type&>; } +// expected-note@-1{{because 'Same<expr-type, typename T::type &>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} struct r9 {}; struct M { using type = M; }; @@ -122,6 +127,17 @@ template<typename T> requires requires (T t) { { t } -> IsEven; } // expected-error{{concept named in type constraint is not a type concept}} struct r11 {}; +// Value categories + +template<auto a = 0> +requires requires (int b) { + { a } -> Same<int>; + { b } -> Same<int&>; + { 0 } -> Same<int>; + { static_cast<int&&>(a) } -> Same<int&&>; +} void f1() {} +template void f1<>(); + // C++ [expr.prim.req.compound] Example namespace std_example { template<typename T> concept C1 = @@ -172,4 +188,4 @@ static_assert(C5<char>); template<C5 T> struct C5_check {}; // expected-note{{because 'short' does not satisfy 'C5'}} using c5 = C5_check<short>; // expected-error{{constraints not satisfied for class template 'C5_check' [with T = short]}} -} \ No newline at end of file +} Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -8832,6 +8832,28 @@ return Context.getTypeOfExprType(E); } +/// getDecltypeForParenthesizedExpr - Given an expr, will return the type for +/// that expression, as in [dcl.type.simple]p4 but without taking id-expressions +/// and class member access into account. +static QualType getDecltypeForParenthesizedExpr(Sema &S, Expr *E) { + // C++11 [dcl.type.simple]p4: + // [...] + QualType T = E->getType(); + switch (E->getValueKind()) { + // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the + // type of e; + case VK_XValue: + return S.Context.getRValueReferenceType(T); + // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the + // type of e; + case VK_LValue: + return S.Context.getLValueReferenceType(T); + // - otherwise, decltype(e) is the type of e. + case VK_RValue: + return T; + } +} + /// getDecltypeForExpr - Given an expr, will return the decltype for /// that expression, according to the rules in C++11 /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18. @@ -8896,22 +8918,7 @@ } } - - // C++11 [dcl.type.simple]p4: - // [...] - QualType T = E->getType(); - switch (E->getValueKind()) { - // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the - // type of e; - case VK_XValue: T = S.Context.getRValueReferenceType(T); break; - // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the - // type of e; - case VK_LValue: T = S.Context.getLValueReferenceType(T); break; - // - otherwise, decltype(e) is the type of e. - case VK_RValue: break; - } - - return T; + return getDecltypeForParenthesizedExpr(S, E); } QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc, @@ -8930,6 +8937,11 @@ return Context.getDecltypeType(E, getDecltypeForExpr(*this, E)); } +QualType Sema::getCanonicalTypeForParenthesizedExpr(Expr *E) { + assert(!E->isInstantiationDependent() && "expression must be non-dependant"); + return getDecltypeForParenthesizedExpr(*this, E).getCanonicalType(); +} + QualType Sema::BuildUnaryTransformType(QualType BaseType, UnaryTransformType::UTTKind UKind, SourceLocation Loc) { Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -8662,10 +8662,8 @@ // be satisfied. TemplateParameterList *TPL = ReturnTypeRequirement.getTypeConstraintTemplateParameterList(); - QualType MatchedType = - BuildDecltypeType(E, E->getBeginLoc()).getCanonicalType(); llvm::SmallVector<TemplateArgument, 1> Args; - Args.push_back(TemplateArgument(MatchedType)); + Args.push_back(TemplateArgument(getCanonicalTypeForParenthesizedExpr(E))); TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); MultiLevelTemplateArgumentList MLTAL(TAL); for (unsigned I = 0; I < TPL->getDepth(); ++I) Index: clang/lib/Sema/SemaConcept.cpp =================================================================== --- clang/lib/Sema/SemaConcept.cpp +++ clang/lib/Sema/SemaConcept.cpp @@ -439,18 +439,19 @@ case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { ConceptSpecializationExpr *ConstraintExpr = Req->getReturnTypeRequirementSubstitutedConstraintExpr(); - if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) + if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { // A simple case - expr type is the type being constrained and the concept // was not provided arguments. + Expr *e = Req->getExpr(); S.Diag(ConstraintExpr->getBeginLoc(), diag::note_expr_requirement_constraints_not_satisfied_simple) - << (int)First << S.BuildDecltypeType(Req->getExpr(), - Req->getExpr()->getBeginLoc()) + << (int)First << e << S.getCanonicalTypeForParenthesizedExpr(e) << ConstraintExpr->getNamedConcept(); - else + } else { S.Diag(ConstraintExpr->getBeginLoc(), diag::note_expr_requirement_constraints_not_satisfied) << (int)First << ConstraintExpr; + } S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); break; } Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -2284,6 +2284,7 @@ const CXXScopeSpec &SS, QualType T, TagDecl *OwnedTagDecl = nullptr); + QualType getCanonicalTypeForParenthesizedExpr(Expr *E); QualType BuildTypeofExprType(Expr *E, SourceLocation Loc); /// If AsUnevaluated is false, E is treated as though it were an evaluated /// context, such as when building a type for decltype(auto). Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2758,7 +2758,7 @@ def note_expr_requirement_constraints_not_satisfied : Note< "%select{and|because}0 type constraint '%1' was not satisfied:">; def note_expr_requirement_constraints_not_satisfied_simple : Note< - "%select{and|because}0 %1 does not satisfy %2:">; + "%select{and|because}0 'decltype((%1))' (aka %2) does not satisfy %3:">; def note_type_requirement_substitution_error : Note< "%select{and|because}0 '%1' would be invalid: %2">; def note_type_requirement_unknown_substitution_error : Note<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits