[libcxx-commits] [clang] [libcxx] [Clang] Add __builtin_invoke and use it in libc++ (PR #116709)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue May 20 10:19:42 PDT 2025
================
@@ -5406,6 +5408,99 @@ ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
RParenLoc, CurFPFeatureOverrides());
}
+ExprResult Sema::BuiltinInvoke(CallExpr *TheCall) {
+ SourceLocation Loc = TheCall->getBeginLoc();
+ auto Args = MutableArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
+ assert(llvm::none_of(Args,
+ [](Expr *Arg) { return Arg->isTypeDependent(); }));
+
+ if (Args.size() == 0) {
+ Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args_at_least)
+ << /*callee_type=*/0 << /*min_arg_count=*/1 << /*actual_arg_count=*/0
+ << /*is_non_object=*/0 << TheCall->getSourceRange();
+ return ExprError();
+ }
+
+ auto FuncT = Args[0]->getType();
+
+ if (auto *MPT = FuncT->getAs<MemberPointerType>()) {
+ if (Args.size() < 2) {
+ Diag(TheCall->getBeginLoc(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << /*callee_type=*/0 << /*min_arg_count=*/2 << /*actual_arg_count=*/1
+ << /*is_non_object=*/0 << TheCall->getSourceRange();
+ return ExprError();
+ }
+
+ auto *MemPtrClass = MPT->getQualifier()->getAsType();
+ auto ObjectT = Args[1]->getType();
+
+ if (MPT->isMemberDataPointer() && checkArgCount(TheCall, 2))
+ return ExprError();
+
+ ExprResult ObjectArg = [&]() -> ExprResult {
+ // (1.1): (t1.*f)(t2, …, tN) when f is a pointer to a member function of a
+ // class T and is_same_v<T, remove_cvref_t<decltype(t1)>> ||
+ // is_base_of_v<T, remove_cvref_t<decltype(t1)>> is true;
+ // (1.4): t1.*f when N=1 and f is a pointer to data member of a class T
+ // and is_same_v<T, remove_cvref_t<decltype(t1)>> ||
+ // is_base_of_v<T, remove_cvref_t<decltype(t1)>> is true;
+ if (Context.hasSameType(QualType(MemPtrClass, 0),
+ BuiltinRemoveCVRef(ObjectT, Loc)) ||
+ BuiltinIsBaseOf(Args[1]->getBeginLoc(), QualType(MemPtrClass, 0),
+ BuiltinRemoveCVRef(ObjectT, Loc))) {
+ return Args[1];
+ }
+
+ // (t1.get().*f)(t2, …, tN) when f is a pointer to a member function of
+ // a class T and remove_cvref_t<decltype(t1)> is a specialization of
+ // reference_wrapper;
+ if (auto *RD = ObjectT->getAsCXXRecordDecl()) {
+ if (RD->isInStdNamespace() &&
+ RD->getDeclName().getAsString() == "reference_wrapper") {
+ CXXScopeSpec SS;
+ IdentifierInfo *GetName = &Context.Idents.get("get");
+ UnqualifiedId GetID;
+ GetID.setIdentifier(GetName, Loc);
+
+ auto MemExpr = ActOnMemberAccessExpr(
+ getCurScope(), Args[1], Loc, tok::period, SS,
+ /*TemplateKWLoc=*/SourceLocation(), GetID, nullptr);
+
----------------
cor3ntin wrote:
Can you check that this SFINAE properly?
https://github.com/llvm/llvm-project/pull/116709
More information about the libcxx-commits
mailing list