[llvm-branch-commits] [clang] b9be17a - [clang] fix crash on template instantiation of invalid requires expressions
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Aug 16 20:37:13 PDT 2021
Author: Matheus Izvekov
Date: 2021-08-16T20:36:52-07:00
New Revision: b9be17a7ecf960864490349401ca0d2dbba27c8b
URL: https://github.com/llvm/llvm-project/commit/b9be17a7ecf960864490349401ca0d2dbba27c8b
DIFF: https://github.com/llvm/llvm-project/commit/b9be17a7ecf960864490349401ca0d2dbba27c8b.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 <mizvekov at gmail.com>
Reviewed By: rsmith
Differential Revision: https://reviews.llvm.org/D107399
(cherry picked from commit e64e6924b8aef8d48117beb6e87162109ac2512c)
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 f18f77d3442a1..74889aa3ca888 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 15cbe66378450..5433cfb21955d 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 at -1 {{because 'T::a' would be invalid: no member named 'a' in 'PR48656::T1'}}
+
+template <C...> struct A {};
+// expected-note at -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 at -1 {{constraints not satisfied}}
+ // expected-note at -2 {{type 'int' cannot be used prior to '::'}}
+};
+template <typename... Args> void t3(Args... args) { (..., T3<int>::m(args)); }
+// expected-error at -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 593902c6b74d9..d80710937cdfa 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'}}
More information about the llvm-branch-commits
mailing list