clang 22.0.0git
CIRGenExprCXX.cpp
Go to the documentation of this file.
1//===--- CIRGenExprCXX.cpp - Emit CIR Code for C++ expressions ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with code generation of C++ expressions
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
15#include "CIRGenFunction.h"
16
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/ExprCXX.h"
21
22using namespace clang;
23using namespace clang::CIRGen;
24
25namespace {
26struct MemberCallInfo {
27 RequiredArgs reqArgs;
28 // Number of prefix arguments for the call. Ignores the `this` pointer.
29 unsigned prefixSize;
30};
31} // namespace
32
34 CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr,
35 mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce,
36 CallArgList &args, CallArgList *rtlArgs) {
37 assert(ce == nullptr || isa<CXXMemberCallExpr>(ce) ||
39 assert(md->isInstance() &&
40 "Trying to emit a member or operator call expr on a static method!");
41
42 // Push the this ptr.
43 const CXXRecordDecl *rd =
45 args.add(RValue::get(thisPtr), cgf.getTypes().deriveThisType(rd, md));
46
47 // If there is an implicit parameter (e.g. VTT), emit it.
48 if (implicitParam) {
49 args.add(RValue::get(implicitParam), implicitParamTy);
50 }
51
52 const auto *fpt = md->getType()->castAs<FunctionProtoType>();
53 RequiredArgs required =
55 unsigned prefixSize = args.size() - 1;
56
57 // Add the rest of the call args
58 if (rtlArgs) {
59 // Special case: if the caller emitted the arguments right-to-left already
60 // (prior to emitting the *this argument), we're done. This happens for
61 // assignment operators.
62 args.addFrom(*rtlArgs);
63 } else if (ce) {
64 // Special case: skip first argument of CXXOperatorCall (it is "this").
65 unsigned argsToSkip = isa<CXXOperatorCallExpr>(ce) ? 1 : 0;
66 cgf.emitCallArgs(args, fpt, drop_begin(ce->arguments(), argsToSkip),
67 ce->getDirectCallee());
68 } else {
69 assert(
70 fpt->getNumParams() == 0 &&
71 "No CallExpr specified for function with non-zero number of arguments");
72 }
73
74 // return {required, prefixSize};
75 return {required, prefixSize};
76}
77
80 bool hasQualifier, NestedNameSpecifier qualifier, bool isArrow,
81 const Expr *base) {
83
84 // Compute the object pointer.
85 bool canUseVirtualCall = md->isVirtual() && !hasQualifier;
86 const CXXMethodDecl *devirtualizedMethod = nullptr;
88
89 // Note on trivial assignment
90 // --------------------------
91 // Classic codegen avoids generating the trivial copy/move assignment operator
92 // when it isn't necessary, choosing instead to just produce IR with an
93 // equivalent effect. We have chosen not to do that in CIR, instead emitting
94 // trivial copy/move assignment operators and allowing later transformations
95 // to optimize them away if appropriate.
96
97 // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
98 // operator before the LHS.
99 CallArgList rtlArgStorage;
100 CallArgList *rtlArgs = nullptr;
101 if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
102 if (oce->isAssignmentOp()) {
103 rtlArgs = &rtlArgStorage;
104 emitCallArgs(*rtlArgs, md->getType()->castAs<FunctionProtoType>(),
105 drop_begin(ce->arguments(), 1), ce->getDirectCallee(),
106 /*ParamsToSkip*/ 0);
107 }
108 }
109
110 LValue thisPtr;
111 if (isArrow) {
112 LValueBaseInfo baseInfo;
114 Address thisValue = emitPointerWithAlignment(base, &baseInfo);
115 thisPtr = makeAddrLValue(thisValue, base->getType(), baseInfo);
116 } else {
117 thisPtr = emitLValue(base);
118 }
119
120 if (isa<CXXConstructorDecl>(md)) {
121 cgm.errorNYI(ce->getSourceRange(),
122 "emitCXXMemberOrOperatorMemberCallExpr: constructor call");
123 return RValue::get(nullptr);
124 }
125
126 if ((md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion())) &&
128 return RValue::get(nullptr);
129
130 // Compute the function type we're calling
131 const CXXMethodDecl *calleeDecl =
132 devirtualizedMethod ? devirtualizedMethod : md;
133 const CIRGenFunctionInfo *fInfo = nullptr;
134 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl))
135 fInfo = &cgm.getTypes().arrangeCXXStructorDeclaration(
137 else
138 fInfo = &cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);
139
140 cir::FuncType ty = cgm.getTypes().getFunctionType(*fInfo);
141
144
145 // C++ [class.virtual]p12:
146 // Explicit qualification with the scope operator (5.1) suppresses the
147 // virtual call mechanism.
148 //
149 // We also don't emit a virtual call if the base expression has a record type
150 // because then we know what the type is.
151 bool useVirtualCall = canUseVirtualCall && !devirtualizedMethod;
152
153 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl)) {
154 assert(ce->arg_begin() == ce->arg_end() &&
155 "Destructor shouldn't have explicit parameters");
156 assert(returnValue.isNull() && "Destructor shouldn't have return value");
157 if (useVirtualCall) {
158 cgm.getCXXABI().emitVirtualDestructorCall(*this, dtor, Dtor_Complete,
159 thisPtr.getAddress(),
161 } else {
162 GlobalDecl globalDecl(dtor, Dtor_Complete);
163 CIRGenCallee callee;
165 if (!devirtualizedMethod) {
167 cgm.getAddrOfCXXStructor(globalDecl, fInfo, ty), globalDecl);
168 } else {
169 cgm.errorNYI(ce->getSourceRange(), "devirtualized destructor call");
170 return RValue::get(nullptr);
171 }
172
173 QualType thisTy =
174 isArrow ? base->getType()->getPointeeType() : base->getType();
175 // CIRGen does not pass CallOrInvoke here (different from OG LLVM codegen)
176 // because in practice it always null even in OG.
177 emitCXXDestructorCall(globalDecl, callee, thisPtr.getPointer(), thisTy,
178 /*implicitParam=*/nullptr,
179 /*implicitParamTy=*/QualType(), ce);
180 }
181 return RValue::get(nullptr);
182 }
183
184 CIRGenCallee callee;
185 if (useVirtualCall) {
186 callee = CIRGenCallee::forVirtual(ce, md, thisPtr.getAddress(), ty);
187 } else {
189 if (getLangOpts().AppleKext) {
190 cgm.errorNYI(ce->getSourceRange(),
191 "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");
192 return RValue::get(nullptr);
193 }
194
195 callee = CIRGenCallee::forDirect(cgm.getAddrOfFunction(calleeDecl, ty),
196 GlobalDecl(calleeDecl));
197 }
198
199 if (md->isVirtual()) {
200 Address newThisAddr =
201 cgm.getCXXABI().adjustThisArgumentForVirtualFunctionCall(
202 *this, calleeDecl, thisPtr.getAddress(), useVirtualCall);
203 thisPtr.setAddress(newThisAddr);
204 }
205
207 calleeDecl, callee, returnValue, thisPtr.getPointer(),
208 /*ImplicitParam=*/nullptr, QualType(), ce, rtlArgs);
209}
210
211RValue
213 const CXXMethodDecl *md,
215 assert(md->isInstance() &&
216 "Trying to emit a member call expr on a static method!");
218 e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt,
219 /*IsArrow=*/false, e->getArg(0));
220}
221
223 const CXXMethodDecl *md, const CIRGenCallee &callee,
224 ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam,
225 QualType implicitParamTy, const CallExpr *ce, CallArgList *rtlArgs) {
226 const auto *fpt = md->getType()->castAs<FunctionProtoType>();
227 CallArgList args;
228 MemberCallInfo callInfo = commonBuildCXXMemberOrOperatorCall(
229 *this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);
230 auto &fnInfo = cgm.getTypes().arrangeCXXMethodCall(
231 args, fpt, callInfo.reqArgs, callInfo.prefixSize);
232 assert((ce || currSrcLoc) && "expected source location");
233 mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
235 return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
236}
237
239 Address destPtr,
240 const CXXRecordDecl *base) {
241 if (base->isEmpty())
242 return;
243
244 const ASTRecordLayout &layout = cgf.getContext().getASTRecordLayout(base);
245 CharUnits nvSize = layout.getNonVirtualSize();
246
247 // We cannot simply zero-initialize the entire base sub-object if vbptrs are
248 // present, they are initialized by the most derived class before calling the
249 // constructor.
251 stores.emplace_back(CharUnits::Zero(), nvSize);
252
253 // Each store is split by the existence of a vbptr.
254 // TODO(cir): This only needs handling for the MS CXXABI.
256
257 // If the type contains a pointer to data member we can't memset it to zero.
258 // Instead, create a null constant and copy it to the destination.
259 // TODO: there are other patterns besides zero that we can usefully memset,
260 // like -1, which happens to be the pattern used by member-pointers.
261 // TODO: isZeroInitializable can be over-conservative in the case where a
262 // virtual base contains a member pointer.
263 mlir::TypedAttr nullConstantForBase = cgf.cgm.emitNullConstantForBase(base);
264 if (!cgf.getBuilder().isNullValue(nullConstantForBase)) {
265 cgf.cgm.errorNYI(
266 base->getSourceRange(),
267 "emitNullBaseClassInitialization: base constant is not null");
268 } else {
269 // Otherwise, just memset the whole thing to zero. This is legal
270 // because in LLVM, all default initializers (other than the ones we just
271 // handled above) are guaranteed to have a bit pattern of all zeros.
272 // TODO(cir): When the MS CXXABI is supported, we will need to iterate over
273 // `stores` and create a separate memset for each one. For now, we know that
274 // there will only be one store and it will begin at offset zero, so that
275 // simplifies this code considerably.
276 assert(stores.size() == 1 && "Expected only one store");
277 assert(stores[0].first == CharUnits::Zero() &&
278 "Expected store to begin at offset zero");
279 CIRGenBuilderTy builder = cgf.getBuilder();
280 mlir::Location loc = cgf.getLoc(base->getBeginLoc());
281 builder.createStore(loc, builder.getConstant(loc, nullConstantForBase),
282 destPtr);
283 }
284}
285
287 AggValueSlot dest) {
288 assert(!dest.isIgnored() && "Must have a destination!");
289 const CXXConstructorDecl *cd = e->getConstructor();
290
291 // If we require zero initialization before (or instead of) calling the
292 // constructor, as can be the case with a non-user-provided default
293 // constructor, emit the zero initialization now, unless destination is
294 // already zeroed.
295 if (e->requiresZeroInitialization() && !dest.isZeroed()) {
296 switch (e->getConstructionKind()) {
300 e->getType());
301 break;
305 cd->getParent());
306 break;
307 }
308 }
309
310 // If this is a call to a trivial default constructor, do nothing.
311 if (cd->isTrivial() && cd->isDefaultConstructor())
312 return;
313
314 // Elide the constructor if we're constructing from a temporary
315 if (getLangOpts().ElideConstructors && e->isElidable()) {
316 // FIXME: This only handles the simplest case, where the source object is
317 // passed directly as the first argument to the constructor. This
318 // should also handle stepping through implicit casts and conversion
319 // sequences which involve two steps, with a conversion operator
320 // follwed by a converting constructor.
321 const Expr *srcObj = e->getArg(0);
322 assert(srcObj->isTemporaryObject(getContext(), cd->getParent()));
323 assert(
324 getContext().hasSameUnqualifiedType(e->getType(), srcObj->getType()));
325 emitAggExpr(srcObj, dest);
326 return;
327 }
328
329 if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {
331 emitCXXAggrConstructorCall(cd, arrayType, dest.getAddress(), e, false);
332 } else {
333
335 bool forVirtualBase = false;
336 bool delegating = false;
337
338 switch (e->getConstructionKind()) {
341 break;
343 // We should be emitting a constructor; GlobalDecl will assert this
344 type = curGD.getCtorType();
345 delegating = true;
346 break;
348 forVirtualBase = true;
349 [[fallthrough]];
351 type = Ctor_Base;
352 break;
353 }
354
355 emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);
356 }
357}
358
360 const CXXNewExpr *e) {
361 if (!e->isArray())
362 return CharUnits::Zero();
363
364 // No cookie is required if the operator new[] being used is the
365 // reserved placement operator new[].
367 return CharUnits::Zero();
368
369 return cgf.cgm.getCXXABI().getArrayCookieSize(e);
370}
371
372static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
373 unsigned minElements,
374 mlir::Value &numElements,
375 mlir::Value &sizeWithoutCookie) {
377 mlir::Location loc = cgf.getLoc(e->getSourceRange());
378
379 if (!e->isArray()) {
381 sizeWithoutCookie = cgf.getBuilder().getConstant(
382 loc, cir::IntAttr::get(cgf.sizeTy, typeSize.getQuantity()));
383 return sizeWithoutCookie;
384 }
385
386 // The width of size_t.
387 unsigned sizeWidth = cgf.cgm.getDataLayout().getTypeSizeInBits(cgf.sizeTy);
388
389 // The number of elements can be have an arbitrary integer type;
390 // essentially, we need to multiply it by a constant factor, add a
391 // cookie size, and verify that the result is representable as a
392 // size_t. That's just a gloss, though, and it's wrong in one
393 // important way: if the count is negative, it's an error even if
394 // the cookie size would bring the total size >= 0.
395 //
396 // If the array size is constant, Sema will have prevented negative
397 // values and size overflow.
398
399 // Compute the constant factor.
400 llvm::APInt arraySizeMultiplier(sizeWidth, 1);
401 while (const ConstantArrayType *cat =
403 type = cat->getElementType();
404 arraySizeMultiplier *= cat->getSize();
405 }
406
408 llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity());
409 typeSizeMultiplier *= arraySizeMultiplier;
410
411 // Figure out the cookie size.
412 llvm::APInt cookieSize(sizeWidth,
413 calculateCookiePadding(cgf, e).getQuantity());
414
415 // This will be a size_t.
416 mlir::Value size;
417
418 // Emit the array size expression.
419 // We multiply the size of all dimensions for NumElements.
420 // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
421 const Expr *arraySize = *e->getArraySize();
422 mlir::Attribute constNumElements =
423 ConstantEmitter(cgf.cgm, &cgf)
424 .emitAbstract(arraySize, arraySize->getType());
425 if (constNumElements) {
426 // Get an APInt from the constant
427 const llvm::APInt &count =
428 mlir::cast<cir::IntAttr>(constNumElements).getValue();
429
430 [[maybe_unused]] unsigned numElementsWidth = count.getBitWidth();
431 bool hasAnyOverflow = false;
432
433 // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as
434 // overflow, but that should never happen. The size argument is implicitly
435 // cast to a size_t, so it can never be negative and numElementsWidth will
436 // always equal sizeWidth.
437 assert(!count.isNegative() && "Expected non-negative array size");
438 assert(numElementsWidth == sizeWidth &&
439 "Expected a size_t array size constant");
440
441 // Okay, compute a count at the right width.
442 llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);
443
444 // Scale numElements by that. This might overflow, but we don't
445 // care because it only overflows if allocationSize does too, and
446 // if that overflows then we shouldn't use this.
447 // This emits a constant that may not be used, but we can't tell here
448 // whether it will be needed or not.
449 numElements =
450 cgf.getBuilder().getConstInt(loc, adjustedCount * arraySizeMultiplier);
451
452 // Compute the size before cookie, and track whether it overflowed.
453 bool overflow;
454 llvm::APInt allocationSize =
455 adjustedCount.umul_ov(typeSizeMultiplier, overflow);
456
457 // Sema prevents us from hitting this case
458 assert(!overflow && "Overflow in array allocation size");
459
460 // Add in the cookie, and check whether it's overflowed.
461 if (cookieSize != 0) {
462 // Save the current size without a cookie. This shouldn't be
463 // used if there was overflow
464 sizeWithoutCookie = cgf.getBuilder().getConstInt(
465 loc, allocationSize.zextOrTrunc(sizeWidth));
466
467 allocationSize = allocationSize.uadd_ov(cookieSize, overflow);
468 hasAnyOverflow |= overflow;
469 }
470
471 // On overflow, produce a -1 so operator new will fail
472 if (hasAnyOverflow) {
473 size =
474 cgf.getBuilder().getConstInt(loc, llvm::APInt::getAllOnes(sizeWidth));
475 } else {
476 size = cgf.getBuilder().getConstInt(loc, allocationSize);
477 }
478 } else {
479 // TODO: Handle the variable size case
480 cgf.cgm.errorNYI(e->getSourceRange(),
481 "emitCXXNewAllocSize: variable array size");
482 }
483
484 if (cookieSize == 0)
485 sizeWithoutCookie = size;
486 else
487 assert(sizeWithoutCookie && "didn't set sizeWithoutCookie?");
488
489 return size;
490}
491
492static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,
493 QualType allocType, Address newPtr,
494 AggValueSlot::Overlap_t mayOverlap) {
495 // FIXME: Refactor with emitExprAsInit.
496 switch (cgf.getEvaluationKind(allocType)) {
497 case cir::TEK_Scalar:
498 cgf.emitScalarInit(init, cgf.getLoc(init->getSourceRange()),
499 cgf.makeAddrLValue(newPtr, allocType), false);
500 return;
501 case cir::TEK_Complex:
502 cgf.emitComplexExprIntoLValue(init, cgf.makeAddrLValue(newPtr, allocType),
503 /*isInit*/ true);
504 return;
505 case cir::TEK_Aggregate: {
509 newPtr, allocType.getQualifiers(), AggValueSlot::IsDestructed,
511 cgf.emitAggExpr(init, slot);
512 return;
513 }
514 }
515 llvm_unreachable("bad evaluation kind");
516}
517
519 const CXXNewExpr *e, QualType elementType, mlir::Type elementTy,
520 Address beginPtr, mlir::Value numElements,
521 mlir::Value allocSizeWithoutCookie) {
522 // If we have a type with trivial initialization and no initializer,
523 // there's nothing to do.
524 if (!e->hasInitializer())
525 return;
526
527 unsigned initListElements = 0;
528
529 const Expr *init = e->getInitializer();
530 const InitListExpr *ile = dyn_cast<InitListExpr>(init);
531 if (ile) {
532 cgm.errorNYI(ile->getSourceRange(), "emitNewArrayInitializer: init list");
533 return;
534 }
535
536 // If all elements have already been initialized, skip any further
537 // initialization.
538 auto constOp = mlir::dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
539 if (constOp) {
540 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constOp.getValue());
541 // Just skip out if the constant count is zero.
542 if (constIntAttr && constIntAttr.getUInt() <= initListElements)
543 return;
544 }
545
546 assert(init && "have trailing elements to initialize but no initializer");
547
548 // If this is a constructor call, try to optimize it out, and failing that
549 // emit a single loop to initialize all remaining elements.
550 if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) {
551 CXXConstructorDecl *ctor = cce->getConstructor();
552 if (ctor->isTrivial()) {
553 // If new expression did not specify value-initialization, then there
554 // is no initialization.
555 if (!cce->requiresZeroInitialization())
556 return;
557
558 cgm.errorNYI(cce->getSourceRange(),
559 "emitNewArrayInitializer: trivial ctor zero-init");
560 return;
561 }
562
563 cgm.errorNYI(cce->getSourceRange(),
564 "emitNewArrayInitializer: ctor initializer");
565 return;
566 }
567
568 cgm.errorNYI(init->getSourceRange(),
569 "emitNewArrayInitializer: unsupported initializer");
570 return;
571}
572
574 QualType elementType, mlir::Type elementTy,
575 Address newPtr, mlir::Value numElements,
576 mlir::Value allocSizeWithoutCookie) {
578 if (e->isArray()) {
579 cgf.emitNewArrayInitializer(e, elementType, elementTy, newPtr, numElements,
580 allocSizeWithoutCookie);
581 } else if (const Expr *init = e->getInitializer()) {
582 storeAnyExprIntoOneUnit(cgf, init, e->getAllocatedType(), newPtr,
584 }
585}
586
588 GlobalDecl dtor, const CIRGenCallee &callee, mlir::Value thisVal,
589 QualType thisTy, mlir::Value implicitParam, QualType implicitParamTy,
590 const CallExpr *ce) {
591 const CXXMethodDecl *dtorDecl = cast<CXXMethodDecl>(dtor.getDecl());
592
593 assert(!thisTy.isNull());
594 assert(thisTy->getAsCXXRecordDecl() == dtorDecl->getParent() &&
595 "Pointer/Object mixup");
596
598
599 CallArgList args;
600 commonBuildCXXMemberOrOperatorCall(*this, dtorDecl, thisVal, implicitParam,
601 implicitParamTy, ce, args, nullptr);
602 assert((ce || dtor.getDecl()) && "expected source location provider");
604 return emitCall(cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee,
605 ReturnValueSlot(), args, nullptr,
606 ce ? getLoc(ce->getExprLoc())
607 : getLoc(dtor.getDecl()->getSourceRange()));
608}
609
612 QualType destroyedType = expr->getDestroyedType();
613 if (destroyedType.hasStrongOrWeakObjCLifetime()) {
615 cgm.errorNYI(expr->getExprLoc(),
616 "emitCXXPseudoDestructorExpr: Objective-C lifetime is NYI");
617 } else {
618 // C++ [expr.pseudo]p1:
619 // The result shall only be used as the operand for the function call
620 // operator (), and the result of such a call has type void. The only
621 // effect is the evaluation of the postfix-expression before the dot or
622 // arrow.
623 emitIgnoredExpr(expr->getBase());
624 }
625
626 return RValue::get(nullptr);
627}
628
629/// Emit a call to an operator new or operator delete function, as implicitly
630/// created by new-expressions and delete-expressions.
632 const FunctionDecl *calleeDecl,
633 const FunctionProtoType *calleeType,
634 const CallArgList &args) {
635 cir::CIRCallOpInterface callOrTryCall;
636 cir::FuncOp calleePtr = cgf.cgm.getAddrOfFunction(calleeDecl);
637 CIRGenCallee callee =
638 CIRGenCallee::forDirect(calleePtr, GlobalDecl(calleeDecl));
639 RValue rv =
640 cgf.emitCall(cgf.cgm.getTypes().arrangeFreeFunctionCall(args, calleeType),
641 callee, ReturnValueSlot(), args, &callOrTryCall);
642
643 /// C++1y [expr.new]p10:
644 /// [In a new-expression,] an implementation is allowed to omit a call
645 /// to a replaceable global allocation function.
646 ///
647 /// We model such elidable calls with the 'builtin' attribute.
649 return rv;
650}
651
653 const CallExpr *callExpr,
655 CallArgList args;
656 emitCallArgs(args, type, callExpr->arguments());
657 // Find the allocation or deallocation function that we're calling.
658 ASTContext &astContext = getContext();
659 assert(op == OO_New || op == OO_Delete);
661
662 clang::DeclContextLookupResult lookupResult =
663 astContext.getTranslationUnitDecl()->lookup(name);
664 for (const auto *decl : lookupResult) {
665 if (const auto *funcDecl = dyn_cast<FunctionDecl>(decl)) {
666 if (astContext.hasSameType(funcDecl->getType(), QualType(type, 0))) {
667 if (sanOpts.has(SanitizerKind::AllocToken)) {
668 // TODO: Set !alloc_token metadata.
670 cgm.errorNYI("Alloc token sanitizer not yet supported!");
671 }
672
673 // Emit the call to operator new/delete.
674 return emitNewDeleteCall(*this, funcDecl, type, args);
675 }
676 }
677 }
678
679 llvm_unreachable("predeclared global operator new/delete is missing");
680}
681
682namespace {
683/// Calls the given 'operator delete' on a single object.
684struct CallObjectDelete final : EHScopeStack::Cleanup {
685 mlir::Value ptr;
686 const FunctionDecl *operatorDelete;
687 QualType elementType;
688
689 CallObjectDelete(mlir::Value ptr, const FunctionDecl *operatorDelete,
690 QualType elementType)
691 : ptr(ptr), operatorDelete(operatorDelete), elementType(elementType) {}
692
693 void emit(CIRGenFunction &cgf) override {
694 cgf.emitDeleteCall(operatorDelete, ptr, elementType);
695 }
696};
697} // namespace
698
699/// Emit the code for deleting a single object.
701 Address ptr, QualType elementType) {
702 // C++11 [expr.delete]p3:
703 // If the static type of the object to be deleted is different from its
704 // dynamic type, the static type shall be a base class of the dynamic type
705 // of the object to be deleted and the static type shall have a virtual
706 // destructor or the behavior is undefined.
708
709 const FunctionDecl *operatorDelete = de->getOperatorDelete();
710 assert(!operatorDelete->isDestroyingOperatorDelete());
711
712 // Find the destructor for the type, if applicable. If the
713 // destructor is virtual, we'll just emit the vcall and return.
714 const CXXDestructorDecl *dtor = nullptr;
715 if (const auto *rd = elementType->getAsCXXRecordDecl()) {
716 if (rd->hasDefinition() && !rd->hasTrivialDestructor()) {
717 dtor = rd->getDestructor();
718
719 if (dtor->isVirtual()) {
721 cgf.cgm.getCXXABI().emitVirtualObjectDelete(cgf, de, ptr, elementType,
722 dtor);
723 return;
724 }
725 }
726 }
727
728 // Make sure that we call delete even if the dtor throws.
729 // This doesn't have to a conditional cleanup because we're going
730 // to pop it off in a second.
731 cgf.ehStack.pushCleanup<CallObjectDelete>(
732 NormalAndEHCleanup, ptr.getPointer(), operatorDelete, elementType);
733
734 if (dtor) {
736 /*ForVirtualBase=*/false,
737 /*Delegating=*/false, ptr, elementType);
738 } else if (elementType.getObjCLifetime()) {
740 cgf.cgm.errorNYI(de->getSourceRange(), "emitObjectDelete: ObjCLifetime");
741 }
742
743 // In traditional LLVM codegen null checks are emitted to save a delete call.
744 // In CIR we optimize for size by default, the null check should be added into
745 // this function callers.
747
748 cgf.popCleanupBlock();
749}
750
752 const Expr *arg = e->getArgument();
754
755 // Null check the pointer.
756 //
757 // We could avoid this null check if we can determine that the object
758 // destruction is trivial and doesn't require an array cookie; we can
759 // unconditionally perform the operator delete call in that case. For now, we
760 // assume that deleted pointers are null rarely enough that it's better to
761 // keep the branch. This might be worth revisiting for a -O0 code size win.
762 //
763 // CIR note: emit the code size friendly by default for now, such as mentioned
764 // in `emitObjectDelete`.
766 QualType deleteTy = e->getDestroyedType();
767
768 // A destroying operator delete overrides the entire operation of the
769 // delete expression.
771 cgm.errorNYI(e->getSourceRange(),
772 "emitCXXDeleteExpr: destroying operator delete");
773 return;
774 }
775
776 // We might be deleting a pointer to array.
777 deleteTy = getContext().getBaseElementType(deleteTy);
778 ptr = ptr.withElementType(builder, convertTypeForMem(deleteTy));
779
780 if (e->isArrayForm()) {
782 cgm.errorNYI(e->getSourceRange(), "emitCXXDeleteExpr: array delete");
783 return;
784 } else {
785 emitObjectDelete(*this, e, ptr, deleteTy);
786 }
787}
788
790 // The element type being allocated.
792
793 // 1. Build a call to the allocation function.
794 FunctionDecl *allocator = e->getOperatorNew();
795
796 // If there is a brace-initializer, cannot allocate fewer elements than inits.
797 unsigned minElements = 0;
798
799 mlir::Value numElements = nullptr;
800 mlir::Value allocSizeWithoutCookie = nullptr;
801 mlir::Value allocSize = emitCXXNewAllocSize(
802 *this, e, minElements, numElements, allocSizeWithoutCookie);
803 CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
804
805 // Emit the allocation call.
806 Address allocation = Address::invalid();
807 CallArgList allocatorArgs;
808 if (allocator->isReservedGlobalPlacementOperator()) {
809 cgm.errorNYI(e->getSourceRange(),
810 "emitCXXNewExpr: reserved global placement operator");
811 } else {
812 const FunctionProtoType *allocatorType =
813 allocator->getType()->castAs<FunctionProtoType>();
814 unsigned paramsToSkip = 0;
815
816 // The allocation size is the first argument.
817 QualType sizeType = getContext().getSizeType();
818 allocatorArgs.add(RValue::get(allocSize), sizeType);
819 ++paramsToSkip;
820
821 if (allocSize != allocSizeWithoutCookie) {
822 CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.
823 allocAlign = std::max(allocAlign, cookieAlign);
824 }
825
826 // The allocation alignment may be passed as the second argument.
827 if (e->passAlignment()) {
828 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: pass alignment");
829 }
830
831 // FIXME: Why do we not pass a CalleeDecl here?
832 emitCallArgs(allocatorArgs, allocatorType, e->placement_arguments(),
833 AbstractCallee(), paramsToSkip);
834 RValue rv =
835 emitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
836
837 // Set !heapallocsite metadata on the call to operator new.
839
840 // If this was a call to a global replaceable allocation function that does
841 // not take an alignment argument, the allocator is known to produce storage
842 // that's suitably aligned for any object that fits, up to a known
843 // threshold. Otherwise assume it's suitably aligned for the allocated type.
844 CharUnits allocationAlign = allocAlign;
845 if (!e->passAlignment() &&
846 allocator->isReplaceableGlobalAllocationFunction()) {
847 const TargetInfo &target = cgm.getASTContext().getTargetInfo();
848 unsigned allocatorAlign = llvm::bit_floor(std::min<uint64_t>(
849 target.getNewAlign(), getContext().getTypeSize(allocType)));
850 allocationAlign = std::max(
851 allocationAlign, getContext().toCharUnitsFromBits(allocatorAlign));
852 }
853
854 mlir::Value allocPtr = rv.getValue();
855 allocation = Address(
856 allocPtr, mlir::cast<cir::PointerType>(allocPtr.getType()).getPointee(),
857 allocationAlign);
858 }
859
860 // Emit a null check on the allocation result if the allocation
861 // function is allowed to return null (because it has a non-throwing
862 // exception spec or is the reserved placement new) and we have an
863 // interesting initializer will be running sanitizers on the initialization.
864 bool nullCheck = e->shouldNullCheckAllocation() &&
865 (!allocType.isPODType(getContext()) || e->hasInitializer());
867 if (nullCheck)
868 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: null check");
869
870 // If there's an operator delete, enter a cleanup to call it if an
871 // exception is thrown.
872 if (e->getOperatorDelete() &&
874 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");
875
876 if (allocSize != allocSizeWithoutCookie) {
877 assert(e->isArray());
878 allocation = cgm.getCXXABI().initializeArrayCookie(
879 *this, allocation, numElements, e, allocType);
880 }
881
882 mlir::Type elementTy;
883 if (e->isArray()) {
884 // For array new, use the allocated type to handle multidimensional arrays
885 // correctly
886 elementTy = convertTypeForMem(e->getAllocatedType());
887 } else {
888 elementTy = convertTypeForMem(allocType);
889 }
890 Address result = builder.createElementBitCast(getLoc(e->getSourceRange()),
891 allocation, elementTy);
892
893 // Passing pointer through launder.invariant.group to avoid propagation of
894 // vptrs information which may be included in previous type.
895 // To not break LTO with different optimizations levels, we do it regardless
896 // of optimization level.
897 if (cgm.getCodeGenOpts().StrictVTablePointers &&
898 allocator->isReservedGlobalPlacementOperator())
899 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: strict vtable pointers");
900
902
903 emitNewInitializer(*this, e, allocType, elementTy, result, numElements,
904 allocSizeWithoutCookie);
905 return result.getPointer();
906}
907
909 mlir::Value ptr, QualType deleteTy) {
911
912 const auto *deleteFTy = deleteFD->getType()->castAs<FunctionProtoType>();
913 CallArgList deleteArgs;
914
915 UsualDeleteParams params = deleteFD->getUsualDeleteParams();
916 auto paramTypeIt = deleteFTy->param_type_begin();
917
918 // Pass std::type_identity tag if present
920 cgm.errorNYI(deleteFD->getSourceRange(),
921 "emitDeleteCall: type aware delete");
922
923 // Pass the pointer itself.
924 QualType argTy = *paramTypeIt++;
925 mlir::Value deletePtr =
926 builder.createBitcast(ptr.getLoc(), ptr, convertType(argTy));
927 deleteArgs.add(RValue::get(deletePtr), argTy);
928
929 // Pass the std::destroying_delete tag if present.
930 if (params.DestroyingDelete)
931 cgm.errorNYI(deleteFD->getSourceRange(),
932 "emitDeleteCall: destroying delete");
933
934 // Pass the size if the delete function has a size_t parameter.
935 if (params.Size) {
936 QualType sizeType = *paramTypeIt++;
937 CharUnits deleteTypeSize = getContext().getTypeSizeInChars(deleteTy);
938 assert(mlir::isa<cir::IntType>(convertType(sizeType)) &&
939 "expected cir::IntType");
940 cir::ConstantOp size = builder.getConstInt(
941 *currSrcLoc, convertType(sizeType), deleteTypeSize.getQuantity());
942
943 deleteArgs.add(RValue::get(size), sizeType);
944 }
945
946 // Pass the alignment if the delete function has an align_val_t parameter.
947 if (isAlignedAllocation(params.Alignment))
948 cgm.errorNYI(deleteFD->getSourceRange(),
949 "emitDeleteCall: aligned allocation");
950
951 assert(paramTypeIt == deleteFTy->param_type_end() &&
952 "unknown parameter to usual delete function");
953
954 // Emit the call to delete.
955 emitNewDeleteCall(*this, deleteFD, deleteFTy, deleteArgs);
956}
957
958static mlir::Value emitDynamicCastToNull(CIRGenFunction &cgf,
959 mlir::Location loc, QualType destTy) {
960 mlir::Type destCIRTy = cgf.convertType(destTy);
961 assert(mlir::isa<cir::PointerType>(destCIRTy) &&
962 "result of dynamic_cast should be a ptr");
963
964 if (!destTy->isPointerType()) {
965 mlir::Region *currentRegion = cgf.getBuilder().getBlock()->getParent();
966 /// C++ [expr.dynamic.cast]p9:
967 /// A failed cast to reference type throws std::bad_cast
968 cgf.cgm.getCXXABI().emitBadCastCall(cgf, loc);
969
970 // The call to bad_cast will terminate the current block. Create a new block
971 // to hold any follow up code.
972 cgf.getBuilder().createBlock(currentRegion, currentRegion->end());
973 }
974
975 return cgf.getBuilder().getNullPtr(destCIRTy, loc);
976}
977
979 const CXXDynamicCastExpr *dce) {
980 mlir::Location loc = getLoc(dce->getSourceRange());
981
982 cgm.emitExplicitCastExprType(dce, this);
983 QualType destTy = dce->getTypeAsWritten();
984 QualType srcTy = dce->getSubExpr()->getType();
985
986 // C++ [expr.dynamic.cast]p7:
987 // If T is "pointer to cv void," then the result is a pointer to the most
988 // derived object pointed to by v.
989 bool isDynCastToVoid = destTy->isVoidPointerType();
990 bool isRefCast = destTy->isReferenceType();
991
992 QualType srcRecordTy;
993 QualType destRecordTy;
994 if (isDynCastToVoid) {
995 srcRecordTy = srcTy->getPointeeType();
996 // No destRecordTy.
997 } else if (const PointerType *destPTy = destTy->getAs<PointerType>()) {
998 srcRecordTy = srcTy->castAs<PointerType>()->getPointeeType();
999 destRecordTy = destPTy->getPointeeType();
1000 } else {
1001 srcRecordTy = srcTy;
1002 destRecordTy = destTy->castAs<ReferenceType>()->getPointeeType();
1003 }
1004
1005 assert(srcRecordTy->isRecordType() && "source type must be a record type!");
1007
1008 if (dce->isAlwaysNull())
1009 return emitDynamicCastToNull(*this, loc, destTy);
1010
1011 auto destCirTy = mlir::cast<cir::PointerType>(convertType(destTy));
1012 return cgm.getCXXABI().emitDynamicCast(*this, loc, srcRecordTy, destRecordTy,
1013 destCirTy, isRefCast, thisAddr);
1014}
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address newPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
static void emitObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de, Address ptr, QualType elementType)
Emit the code for deleting a single object.
static void emitNullBaseClassInitialization(CIRGenFunction &cgf, Address destPtr, const CXXRecordDecl *base)
static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e, unsigned minElements, mlir::Value &numElements, mlir::Value &sizeWithoutCookie)
static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init, QualType allocType, Address newPtr, AggValueSlot::Overlap_t mayOverlap)
static CharUnits calculateCookiePadding(CIRGenFunction &cgf, const CXXNewExpr *e)
static mlir::Value emitDynamicCastToNull(CIRGenFunction &cgf, mlir::Location loc, QualType destTy)
static MemberCallInfo commonBuildCXXMemberOrOperatorCall(CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr, mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce, CallArgList &args, CallArgList *rtlArgs)
static RValue emitNewDeleteCall(CIRGenFunction &cgf, const FunctionDecl *calleeDecl, const FunctionProtoType *calleeType, const CallArgList &args)
Emit a call to an operator new or operator delete function, as implicitly created by new-expressions ...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines an enumeration for C++ overloaded operators.
static QualType getPointeeType(const MemRegion *R)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
DeclarationNameTable DeclarationNames
Definition ASTContext.h:776
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
mlir::Value getPointer() const
Definition Address.h:84
static Address invalid()
Definition Address.h:69
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
An aggregate value slot.
IsZeroed_t isZeroed() const
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
bool isNullValue(mlir::Attribute attr) const
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
virtual void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de, Address ptr, QualType elementType, const CXXDestructorDecl *dtor)=0
virtual const clang::CXXRecordDecl * getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md)
Get the type of the implicit "this" parameter used by a method.
virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc)=0
virtual CharUnits getArrayCookieSize(const CXXNewExpr *e)
Returns the extra size required in order to store the array cookie for the given new-expression.
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:90
static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)
Definition CIRGenCall.h:152
An abstract representation of regular/ObjC call/message targets.
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
CIRGenTypes & getTypes() const
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
const clang::LangOptions & getLangOpts() const
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
RValue emitCXXMemberOrOperatorCall(const clang::CXXMethodDecl *md, const CIRGenCallee &callee, ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam, clang::QualType implicitParamTy, const clang::CallExpr *ce, CallArgList *rtlArgs)
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
Address returnValue
The temporary alloca to hold the return value.
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
CIRGenBuilderTy & getBuilder()
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, const CallExpr *callExpr, OverloadedOperatorKind op)
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
RValue emitCXXMemberOrOperatorMemberCallExpr(const clang::CallExpr *ce, const clang::CXXMethodDecl *md, ReturnValueSlot returnValue, bool hasQualifier, clang::NestedNameSpecifier qualifier, bool isArrow, const clang::Expr *base)
void emitCXXDeleteExpr(const CXXDeleteExpr *e)
RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e, const CXXMethodDecl *md, ReturnValueSlot returnValue)
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void popCleanupBlock()
Pops a cleanup block.
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)
Return a null constant appropriate for zero-initializing a base class with the given type.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
const cir::CIRDataLayout getDataLayout() const
CIRGenCXXABI & getCXXABI() const
const CIRGenFunctionInfo & arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType)
clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, const clang::CXXMethodDecl *md)
Derives the 'this' type for CIRGen purposes, i.e.
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
Definition CIRGenCall.h:242
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:233
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
Information for lazily generating a cleanup.
Address getAddress() const
mlir::Value getPointer() const
void setAddress(Address address)
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
A class for recording the number of arguments that a function signature requires.
static RequiredArgs getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:254
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
bool isElidable() const
Whether this construction is elidable.
Definition ExprCXX.h:1617
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1691
bool requiresZeroInitialization() const
Whether this construction first requires zero-initialization before the initializer is called.
Definition ExprCXX.h:1650
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1611
CXXConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Definition ExprCXX.h:1659
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:2999
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2626
FunctionDecl * getOperatorDelete() const
Definition ExprCXX.h:2665
bool isArrayForm() const
Definition ExprCXX.h:2652
QualType getDestroyedType() const
Retrieve the type being destroyed.
Definition ExprCXX.cpp:338
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition ExprCXX.h:481
bool isAlwaysNull() const
isAlwaysNull - Return whether the result of the dynamic_cast is proven to always be null.
Definition ExprCXX.cpp:838
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
bool isVirtual() const
Definition DeclCXX.h:2184
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
bool isInstance() const
Definition DeclCXX.h:2156
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2355
bool isArray() const
Definition ExprCXX.h:2464
llvm::iterator_range< arg_iterator > placement_arguments()
Definition ExprCXX.h:2572
QualType getAllocatedType() const
Definition ExprCXX.h:2434
std::optional< Expr * > getArraySize()
This might return std::nullopt even if isArray() returns true, since there might not be an array size...
Definition ExprCXX.h:2469
bool hasInitializer() const
Whether this new-expression has any initializer at all.
Definition ExprCXX.h:2524
bool shouldNullCheckAllocation() const
True if the allocation result needs to be null-checked.
Definition ExprCXX.cpp:326
bool passAlignment() const
Indicates whether the required alignment should be implicitly passed to the allocation function.
Definition ExprCXX.h:2551
FunctionDecl * getOperatorDelete() const
Definition ExprCXX.h:2461
SourceRange getSourceRange() const
Definition ExprCXX.h:2610
FunctionDecl * getOperatorNew() const
Definition ExprCXX.h:2459
Expr * getInitializer()
The initializer of this new-expression.
Definition ExprCXX.h:2533
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:84
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Definition ExprCXX.h:2745
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1186
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3081
arg_iterator arg_begin()
Definition Expr.h:3134
arg_iterator arg_end()
Definition Expr.h:3137
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
arg_range arguments()
Definition Expr.h:3129
Expr * getSubExpr()
Definition Expr.h:3660
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3760
The results of name lookup within a DeclContext.
Definition DeclBase.h:1382
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
The name of a declaration.
QualType getTypeAsWritten() const
getTypeAsWritten - Returns the type that this expression is casting to, as written in the source code...
Definition Expr.h:3889
This represents one expression.
Definition Expr.h:112
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const
Determine whether the result of this expression is a temporary object of the given class type.
Definition Expr.cpp:3248
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2000
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3545
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
UsualDeleteParams getUsualDeleteParams() const
Definition Decl.cpp:3561
bool isReservedGlobalPlacementOperator() const
Determines whether this operator new or delete is one of the reserved global placement operators: voi...
Definition Decl.cpp:3397
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2385
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4543
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5254
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
Describes an C or C++ initializer list.
Definition Expr.h:5233
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8318
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1438
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
Definition Type.cpp:2694
bool hasStrongOrWeakObjCLifetime() const
Definition TypeBase.h:1446
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3573
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4887
bool isUnion() const
Definition Decl.h:3922
Exposes information about the current target.
Definition TargetInfo.h:226
unsigned getNewAlign() const
Return the largest alignment for which a suitably-sized allocation with 'operator new(size_t)' is gua...
Definition TargetInfo.h:764
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3547
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isVoidPointerType() const
Definition Type.cpp:712
bool isPointerType() const
Definition TypeBase.h:8515
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
bool isReferenceType() const
Definition TypeBase.h:8539
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
bool isRecordType() const
Definition TypeBase.h:8642
QualType getType() const
Definition Decl.h:723
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isAlignedAllocation(AlignedAllocationMode Mode)
Definition ExprCXX.h:2265
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
bool isTypeAwareAllocation(TypeAwareAllocationMode Mode)
Definition ExprCXX.h:2253
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool objCLifetime()
static bool addressSpace()
static bool devirtualizeDestructor()
static bool aggValueSlotGC()
static bool devirtualizeMemberFunction()
static bool deleteArray()
static bool emitTypeCheck()
static bool opCallMustTail()
static bool exprNewNullCheck()
static bool attributeBuiltin()
static bool emitNullCheckForDeleteCalls()
static bool generateDebugInfo()
clang::CharUnits getSizeAlign() const
The parameters to pass to a usual operator delete.
Definition ExprCXX.h:2344
TypeAwareAllocationMode TypeAwareDelete
Definition ExprCXX.h:2345
AlignedAllocationMode Alignment
Definition ExprCXX.h:2348