mizvekov created this revision. mizvekov published this revision for review. mizvekov added a reviewer: rsmith. Herald added a project: clang. Herald added a subscriber: cfe-commits.
See PR48656. The implementation of the template instantiation of requires expression was incorrectly trying to get the expression from an 'ExprRequirement' before checking if it was an error state. Signed-off-by: Matheus Izvekov <mizve...@gmail.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D107399 Files: clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp Index: clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -192,3 +192,29 @@ using c3 = C2_check<has_inner>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}} using c4 = C3_check<void>; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}} } + +namespace PR48656 { + +template <typename T> concept C = requires { requires requires { T::a; }; }; +// expected-note@-1 {{because 'T::a' would be invalid: no member named 'a' in 'PR48656::T1'}} + +template <C...> struct A {}; +// expected-note@-1 {{because 'PR48656::T1' does not satisfy 'C'}} + +struct T1 {}; +template struct A<T1>; // expected-error {{constraints not satisfied for class template 'A' [with $0 = <PR48656::T1>]}} + +struct T2 { static constexpr bool a = false; }; +template struct A<T2>; + +template<typename T> struct T3 { + static void m(auto) requires requires { T::fail; } {} + // expected-note@-1 {{constraints not satisfied}} + // expected-note@-2 {{type 'int' cannot be used prior to '::'}} +}; +template<typename... Args> void t3(Args... args) { (..., T3<int>::m(args)); } +// expected-error@-1 {{no matching function for call to 'm'}} + +template void t3<int>(int); // expected-note {{requested here}} + +} // namespace PR48656 Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1934,25 +1934,23 @@ return Req; Sema::SFINAETrap Trap(SemaRef); - TemplateDeductionInfo Info(Req->getExpr()->getBeginLoc()); llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *> TransExpr; if (Req->isExprSubstitutionFailure()) TransExpr = Req->getExprSubstitutionDiagnostic(); else { - Sema::InstantiatingTemplate ExprInst(SemaRef, Req->getExpr()->getBeginLoc(), - Req, Info, - Req->getExpr()->getSourceRange()); + Expr *E = Req->getExpr(); + TemplateDeductionInfo Info(E->getBeginLoc()); + Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req, Info, + E->getSourceRange()); if (ExprInst.isInvalid()) return nullptr; - ExprResult TransExprRes = TransformExpr(Req->getExpr()); + ExprResult TransExprRes = TransformExpr(E); if (TransExprRes.isInvalid() || Trap.hasErrorOccurred()) - TransExpr = createSubstDiag(SemaRef, Info, - [&] (llvm::raw_ostream& OS) { - Req->getExpr()->printPretty(OS, nullptr, - SemaRef.getPrintingPolicy()); - }); + TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream &OS) { + E->printPretty(OS, nullptr, SemaRef.getPrintingPolicy()); + }); else TransExpr = TransExprRes.get(); } @@ -1966,6 +1964,7 @@ else if (RetReq.isTypeConstraint()) { TemplateParameterList *OrigTPL = RetReq.getTypeConstraintTemplateParameterList(); + TemplateDeductionInfo Info(OrigTPL->getTemplateLoc()); Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(), Req, Info, OrigTPL->getSourceRange()); if (TPLInst.isInvalid())
Index: clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -192,3 +192,29 @@ using c3 = C2_check<has_inner>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}} using c4 = C3_check<void>; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}} } + +namespace PR48656 { + +template <typename T> concept C = requires { requires requires { T::a; }; }; +// expected-note@-1 {{because 'T::a' would be invalid: no member named 'a' in 'PR48656::T1'}} + +template <C...> struct A {}; +// expected-note@-1 {{because 'PR48656::T1' does not satisfy 'C'}} + +struct T1 {}; +template struct A<T1>; // expected-error {{constraints not satisfied for class template 'A' [with $0 = <PR48656::T1>]}} + +struct T2 { static constexpr bool a = false; }; +template struct A<T2>; + +template<typename T> struct T3 { + static void m(auto) requires requires { T::fail; } {} + // expected-note@-1 {{constraints not satisfied}} + // expected-note@-2 {{type 'int' cannot be used prior to '::'}} +}; +template<typename... Args> void t3(Args... args) { (..., T3<int>::m(args)); } +// expected-error@-1 {{no matching function for call to 'm'}} + +template void t3<int>(int); // expected-note {{requested here}} + +} // namespace PR48656 Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1934,25 +1934,23 @@ return Req; Sema::SFINAETrap Trap(SemaRef); - TemplateDeductionInfo Info(Req->getExpr()->getBeginLoc()); llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *> TransExpr; if (Req->isExprSubstitutionFailure()) TransExpr = Req->getExprSubstitutionDiagnostic(); else { - Sema::InstantiatingTemplate ExprInst(SemaRef, Req->getExpr()->getBeginLoc(), - Req, Info, - Req->getExpr()->getSourceRange()); + Expr *E = Req->getExpr(); + TemplateDeductionInfo Info(E->getBeginLoc()); + Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req, Info, + E->getSourceRange()); if (ExprInst.isInvalid()) return nullptr; - ExprResult TransExprRes = TransformExpr(Req->getExpr()); + ExprResult TransExprRes = TransformExpr(E); if (TransExprRes.isInvalid() || Trap.hasErrorOccurred()) - TransExpr = createSubstDiag(SemaRef, Info, - [&] (llvm::raw_ostream& OS) { - Req->getExpr()->printPretty(OS, nullptr, - SemaRef.getPrintingPolicy()); - }); + TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream &OS) { + E->printPretty(OS, nullptr, SemaRef.getPrintingPolicy()); + }); else TransExpr = TransExprRes.get(); } @@ -1966,6 +1964,7 @@ else if (RetReq.isTypeConstraint()) { TemplateParameterList *OrigTPL = RetReq.getTypeConstraintTemplateParameterList(); + TemplateDeductionInfo Info(OrigTPL->getTemplateLoc()); Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(), Req, Info, OrigTPL->getSourceRange()); if (TPLInst.isInvalid())
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits