[c++20] Compute exception specifications for defaulted comparisons.
This requires us to essentially fully form the body of the defaulted
comparison, but from an unevaluated context. Naively this would require
generating the function definition twice; instead, we ensure that the
function body is implicitly defined before performing the check, and
walk the actual body where possible.
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 38b9ceb..959cdad 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -205,7 +205,7 @@
// Compute or instantiate the exception specification now.
if (SourceFPT->getExceptionSpecType() == EST_Unevaluated)
- EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl));
+ EvaluateImplicitExceptionSpec(Loc, SourceDecl);
else
InstantiateExceptionSpec(Loc, SourceDecl);
@@ -1221,6 +1221,17 @@
return mergeCanThrow(CT, canSubStmtsThrow(*this, BTE));
}
+ case Expr::PseudoObjectExprClass: {
+ auto *POE = cast<PseudoObjectExpr>(S);
+ CanThrowResult CT = CT_Cannot;
+ for (const Expr *E : POE->semantics()) {
+ CT = mergeCanThrow(CT, canThrow(E));
+ if (CT == CT_Can)
+ break;
+ }
+ return CT;
+ }
+
// ObjC message sends are like function calls, but never have exception
// specs.
case Expr::ObjCMessageExprClass:
@@ -1327,7 +1338,6 @@
case Expr::ObjCAvailabilityCheckExprClass:
case Expr::OffsetOfExprClass:
case Expr::PackExpansionExprClass:
- case Expr::PseudoObjectExprClass:
case Expr::SubstNonTypeTemplateParmExprClass:
case Expr::SubstNonTypeTemplateParmPackExprClass:
case Expr::FunctionParmPackExprClass:
@@ -1335,7 +1345,7 @@
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
case Expr::TypoExprClass:
- // FIXME: Can any of the above throw? If so, when?
+ // FIXME: Many of the above can throw.
return CT_Cannot;
case Expr::AddrLabelExprClass: