================
@@ -9481,6 +9508,595 @@ ComputeDefaultedComparisonExceptionSpec(Sema &S,
SourceLocation Loc,
return ExceptSpec;
}
+static Sema::ImplicitExceptionSpecification
+ComputeDefaultedComparisonExceptionSpec(Sema &S, SourceLocation Loc,
+ FunctionDecl *FD,
+ DefaultedComparisonKind DCK) {
+ auto BuildBody = [&](SourceLocation BodyLoc) {
+ CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(FD->getFriendObjectKind() == Decl::FOK_None
+ ? FD->getDeclContext()
+ : FD->getLexicalDeclContext());
+ return DefaultedComparisonSynthesizer(S, RD, FD, DCK, BodyLoc).build();
+ };
+ return computeExceptionSpecFromSynthesizedBody(S, Loc, FD, BuildBody);
+}
+
+// C++2d [over.inc.default]: defaulted postfix increment and decrement operator
+// functions (P3668R4).
+
+namespace {
+/// Which diagnostics to produce while analyzing a defaulted postfix increment
+/// or decrement operator function.
+enum class PostfixOperatorDiagnoseKind {
+ NoDiagnostics,
+ ExplainDeleted,
+ ExplainConstexpr
+};
+
+/// Information about a defaulted postfix increment or decrement operator
+/// function, as determined by analyzeDefaultedPostfixOperator.
+struct DefaultedPostfixOperatorInfo {
+ /// Whether the function should be defined as deleted.
+ bool Deleted = false;
+ /// Whether every function invoked by the implicit definition is constexpr.
+ bool Constexpr = true;
+};
+} // namespace
+
+/// Get the type of the first parameter of a postfix increment or decrement
+/// operator function, where the implicit object parameter (if any) is
+/// considered to be the first parameter.
+static QualType getPostfixOperatorFirstParamType(const FunctionDecl *FD) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+ return MD->getFunctionObjectParameterReferenceType();
+ return FD->getParamDecl(0)->getType();
+}
+
+/// Get the type C for which a well-formed defaulted postfix increment or
+/// decrement operator function is defaulted.
+static QualType getDefaultedPostfixOperatorType(const FunctionDecl *FD) {
+ return getPostfixOperatorFirstParamType(FD)
+ .getNonReferenceType()
+ .getUnqualifiedType();
+}
+
+/// Determine whether a defaulted postfix increment or decrement operator
+/// function for type \p C should be defined as deleted, as specified in C++2d
+/// [over.inc.default]p2, and whether every function it would invoke is
+/// constexpr.
+static DefaultedPostfixOperatorInfo
+analyzeDefaultedPostfixOperator(Sema &S, FunctionDecl *FD,
+ PostfixOperatorKind Kind, QualType C,
+ PostfixOperatorDiagnoseKind Diagnose) {
+ using DiagnoseKind = PostfixOperatorDiagnoseKind;
+ DefaultedPostfixOperatorInfo Info;
+ SourceLocation Loc = FD->getLocation();
+
+ // C++2d [over.inc.default]p1:
+ // Name lookups and access checks in the implicit definition of a defaulted
+ // postfix increment or decrement operator function are performed from a
+ // context equivalent to its function-body.
+ Sema::ContextRAII SavedContext(S, FD);
+
+ // Let c be an lvalue of type C. c stands for the first parameter (or the
+ // implicit object), which is always an lvalue when named in the function
+ // body, even if it is declared as an rvalue reference.
+ OpaqueValueExpr Obj(Loc, C, VK_LValue);
+ Expr *Args[] = {&Obj};
+
+ auto Deleted = [&] {
+ Info.Deleted = true;
+ return Info;
+ };
+ auto InaccessibleDiag = [&](unsigned Step) {
+ return Diagnose == DiagnoseKind::ExplainDeleted
+ ? S.PDiag(diag::note_defaulted_postfix_operator_inaccessible)
+ << FD << Step
+ : S.PDiag();
+ };
+ auto NoteCallsDeleted = [&](unsigned Step, FunctionDecl *Callee) {
+ if (Diagnose != DiagnoseKind::ExplainDeleted)
+ return;
+ S.Diag(Loc, diag::note_defaulted_postfix_operator_calls_deleted)
+ << FD << Step;
+ if (Callee)
+ S.NoteDeletedFunction(Callee);
+ };
+ auto CheckConstexpr = [&](const FunctionDecl *Callee, unsigned Step) {
+ if (Callee->isConstexpr())
+ return;
+ Info.Constexpr = false;
+ if (Diagnose == DiagnoseKind::ExplainConstexpr)
+ S.Diag(Callee->getLocation(),
+ diag::note_defaulted_postfix_operator_not_constexpr_here)
+ << Step;
+ };
+
+ // C++2d [over.inc.default]p2:
+ // A defaulted postfix increment or decrement operator function for a type
+ // C is defined as deleted if
+ CXXRecordDecl *RD = C->getAsCXXRecordDecl();
+ if (RD) {
----------------
bassiounix wrote:
`RD` is false when `C` is an enum
https://github.com/llvm/llvm-project/pull/229560
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits