@@ -2261,6 +2261,99 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) {
2261
2261
return false;
2262
2262
}
2263
2263
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
+
2264
2357
ExprResult
2265
2358
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2266
2359
CallExpr *TheCall) {
@@ -2420,6 +2513,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2420
2513
return BuiltinShuffleVector(TheCall);
2421
2514
// TheCall will be freed by the smart pointer here, but that's fine, since
2422
2515
// BuiltinShuffleVector guts it, but then doesn't release it.
2516
+ case Builtin::BI__builtin_invoke:
2517
+ return BuiltinInvoke(*this, TheCall);
2423
2518
case Builtin::BI__builtin_prefetch:
2424
2519
if (BuiltinPrefetch(TheCall))
2425
2520
return ExprError();
0 commit comments