@@ -2261,6 +2261,99 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) {
22612261 return false;
22622262}
22632263
2264+ static ExprResult BuiltinInvoke(Sema &S, CallExpr *TheCall) {
2265+ SourceLocation Loc = TheCall->getBeginLoc();
2266+ MutableArrayRef Args(TheCall->getArgs(), TheCall->getNumArgs());
2267+ assert(llvm::none_of(Args, [](Expr *Arg) { return Arg->isTypeDependent(); }));
2268+
2269+ if (Args.size() == 0) {
2270+ S.Diag(TheCall->getBeginLoc(),
2271+ diag::err_typecheck_call_too_few_args_at_least)
2272+ << /*callee_type=*/0 << /*min_arg_count=*/1 << /*actual_arg_count=*/0
2273+ << /*is_non_object=*/0 << TheCall->getSourceRange();
2274+ return ExprError();
2275+ }
2276+
2277+ QualType FuncT = Args[0]->getType();
2278+
2279+ if (const auto *MPT = FuncT->getAs<MemberPointerType>()) {
2280+ if (Args.size() < 2) {
2281+ S.Diag(TheCall->getBeginLoc(),
2282+ diag::err_typecheck_call_too_few_args_at_least)
2283+ << /*callee_type=*/0 << /*min_arg_count=*/2 << /*actual_arg_count=*/1
2284+ << /*is_non_object=*/0 << TheCall->getSourceRange();
2285+ return ExprError();
2286+ }
2287+
2288+ const Type *MemPtrClass = MPT->getQualifier()->getAsType();
2289+ QualType ObjectT = Args[1]->getType();
2290+
2291+ if (MPT->isMemberDataPointer() && S.checkArgCount(TheCall, 2))
2292+ return ExprError();
2293+
2294+ ExprResult ObjectArg = [&]() -> ExprResult {
2295+ // (1.1): (t1.*f)(t2, ..., tN) when f is a pointer to a member function of
2296+ // a class T and is_same_v<T, remove_cvref_t<decltype(t1)>> ||
2297+ // is_base_of_v<T, remove_cvref_t<decltype(t1)>> is true;
2298+ // (1.4): t1.*f when N=1 and f is a pointer to data member of a class T
2299+ // and is_same_v<T, remove_cvref_t<decltype(t1)>> ||
2300+ // is_base_of_v<T, remove_cvref_t<decltype(t1)>> is true;
2301+ if (S.Context.hasSameType(QualType(MemPtrClass, 0),
2302+ S.BuiltinRemoveCVRef(ObjectT, Loc)) ||
2303+ S.BuiltinIsBaseOf(Args[1]->getBeginLoc(), QualType(MemPtrClass, 0),
2304+ S.BuiltinRemoveCVRef(ObjectT, Loc))) {
2305+ return Args[1];
2306+ }
2307+
2308+ // (t1.get().*f)(t2, ..., tN) when f is a pointer to a member function of
2309+ // a class T and remove_cvref_t<decltype(t1)> is a specialization of
2310+ // reference_wrapper;
2311+ if (const auto *RD = ObjectT->getAsCXXRecordDecl()) {
2312+ if (RD->isInStdNamespace() &&
2313+ RD->getDeclName().getAsString() == "reference_wrapper") {
2314+ CXXScopeSpec SS;
2315+ IdentifierInfo *GetName = &S.Context.Idents.get("get");
2316+ UnqualifiedId GetID;
2317+ GetID.setIdentifier(GetName, Loc);
2318+
2319+ ExprResult MemExpr = S.ActOnMemberAccessExpr(
2320+ S.getCurScope(), Args[1], Loc, tok::period, SS,
2321+ /*TemplateKWLoc=*/SourceLocation(), GetID, nullptr);
2322+
2323+ if (MemExpr.isInvalid())
2324+ return ExprError();
2325+
2326+ return S.ActOnCallExpr(S.getCurScope(), MemExpr.get(), Loc, {}, Loc);
2327+ }
2328+ }
2329+
2330+ // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
2331+ // class T and t1 does not satisfy the previous two items;
2332+
2333+ return S.ActOnUnaryOp(S.getCurScope(), Loc, tok::star, Args[1]);
2334+ }();
2335+
2336+ if (ObjectArg.isInvalid())
2337+ return ExprError();
2338+
2339+ ExprResult BinOp = S.ActOnBinOp(S.getCurScope(), TheCall->getBeginLoc(),
2340+ tok::periodstar, ObjectArg.get(), Args[0]);
2341+ if (BinOp.isInvalid())
2342+ return ExprError();
2343+
2344+ if (MPT->isMemberDataPointer())
2345+ return BinOp;
2346+
2347+ auto *MemCall = new (S.Context)
2348+ ParenExpr(SourceLocation(), SourceLocation(), BinOp.get());
2349+
2350+ return S.ActOnCallExpr(S.getCurScope(), MemCall, TheCall->getBeginLoc(),
2351+ Args.drop_front(2), TheCall->getRParenLoc());
2352+ }
2353+ return S.ActOnCallExpr(S.getCurScope(), Args.front(), TheCall->getBeginLoc(),
2354+ Args.drop_front(), TheCall->getRParenLoc());
2355+ }
2356+
22642357ExprResult
22652358Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
22662359 CallExpr *TheCall) {
@@ -2420,6 +2513,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
24202513 return BuiltinShuffleVector(TheCall);
24212514 // TheCall will be freed by the smart pointer here, but that's fine, since
24222515 // BuiltinShuffleVector guts it, but then doesn't release it.
2516+ case Builtin::BI__builtin_invoke:
2517+ return BuiltinInvoke(*this, TheCall);
24232518 case Builtin::BI__builtin_prefetch:
24242519 if (BuiltinPrefetch(TheCall))
24252520 return ExprError();
0 commit comments