Author: Matheus Izvekov Date: 2021-08-03T23:16:04+02:00 New Revision: e64e6924b8aef8d48117beb6e87162109ac2512c
URL: https://github.com/llvm/llvm-project/commit/e64e6924b8aef8d48117beb6e87162109ac2512c DIFF: https://github.com/llvm/llvm-project/commit/e64e6924b8aef8d48117beb6e87162109ac2512c.diff LOG: [clang] fix crash on template instantiation of invalid requires expressions See PR48656. The implementation of the template instantiation of requires expressions 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> Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D107399 Added: Modified: clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index f18f77d3442a..74889aa3ca88 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1934,25 +1934,23 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) { 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 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) { 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()) diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp index 15cbe6637845..5433cfb21955 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -192,3 +192,29 @@ namespace std_example { 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 diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp index 593902c6b74d..d80710937cdf 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp @@ -91,7 +91,7 @@ struct X { template<class T> concept C1 = sizeof(T) != 0; template<class T> concept C2 = C1<typename T::template Y<1>::type>; -template<class T> requires C1<T> void t1() = delete; // expected-note {{candidate function}} +template<class T> requires C1<T> void t1() {}; // expected-note {{candidate function}} template<class T> requires C1<T> && C2<T> void t1() = delete; // expected-note {{candidate function}} template void t1<X>(); void t1() { t1<X>(); } // expected-error {{call to deleted function 't1'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits