clang 22.0.0git
CIRGenClass.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 C++ code generation of classes
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
14#include "CIRGenFunction.h"
15#include "CIRGenValue.h"
16
18#include "clang/AST/ExprCXX.h"
20#include "clang/AST/Type.h"
23
24using namespace clang;
25using namespace clang::CIRGen;
26
27/// Checks whether the given constructor is a valid subject for the
28/// complete-to-base constructor delegation optimization, i.e. emitting the
29/// complete constructor as a simple call to the base constructor.
31 const CXXConstructorDecl *ctor) {
32 // Currently we disable the optimization for classes with virtual bases
33 // because (1) the address of parameter variables need to be consistent across
34 // all initializers but (2) the delegate function call necessarily creates a
35 // second copy of the parameter variable.
36 //
37 // The limiting example (purely theoretical AFAIK):
38 // struct A { A(int &c) { c++; } };
39 // struct A : virtual A {
40 // B(int count) : A(count) { printf("%d\n", count); }
41 // };
42 // ...although even this example could in principle be emitted as a delegation
43 // since the address of the parameter doesn't escape.
44 if (ctor->getParent()->getNumVBases())
45 return false;
46
47 // We also disable the optimization for variadic functions because it's
48 // impossible to "re-pass" varargs.
49 if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
50 return false;
51
52 // FIXME: Decide if we can do a delegation of a delegating constructor.
53 if (ctor->isDelegatingConstructor())
54 return false;
55
56 return true;
57}
58
60 CXXCtorInitializer *memberInit,
61 LValue &lhs) {
62 FieldDecl *field = memberInit->getAnyMember();
63 if (memberInit->isIndirectMemberInitializer()) {
64 // If we are initializing an anonymous union field, drill down to the field.
65 IndirectFieldDecl *indirectField = memberInit->getIndirectMember();
66 for (const auto *nd : indirectField->chain()) {
67 auto *fd = cast<clang::FieldDecl>(nd);
68 lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());
69 }
70 } else {
71 lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());
72 }
73}
74
76 const CXXRecordDecl *classDecl,
77 CXXCtorInitializer *memberInit,
78 const CXXConstructorDecl *constructor,
79 FunctionArgList &args) {
80 assert(memberInit->isAnyMemberInitializer() &&
81 "Must have member initializer!");
82 assert(memberInit->getInit() && "Must have initializer!");
83
85
86 // non-static data member initializers
87 FieldDecl *field = memberInit->getAnyMember();
88 QualType fieldType = field->getType();
89
90 mlir::Value thisPtr = cgf.loadCXXThis();
91 CanQualType recordTy = cgf.getContext().getCanonicalTagType(classDecl);
92
93 // If a base constructor is being emitted, create an LValue that has the
94 // non-virtual alignment.
95 LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)
96 ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)
97 : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);
98
99 emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);
100
101 // Special case: If we are in a copy or move constructor, and we are copying
102 // an array off PODs or classes with trivial copy constructors, ignore the AST
103 // and perform the copy we know is equivalent.
104 // FIXME: This is hacky at best... if we had a bit more explicit information
105 // in the AST, we could generalize it more easily.
106 const ConstantArrayType *array =
107 cgf.getContext().getAsConstantArrayType(fieldType);
108 if (array && constructor->isDefaulted() &&
109 constructor->isCopyOrMoveConstructor()) {
110 QualType baseElementTy = cgf.getContext().getBaseElementType(array);
111 // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
112 // whereas ClangIR wants to represent all object construction explicitly.
113 if (!baseElementTy->isRecordType()) {
114 unsigned srcArgIndex =
115 cgf.cgm.getCXXABI().getSrcArgforCopyCtor(constructor, args);
116 cir::LoadOp srcPtr = cgf.getBuilder().createLoad(
117 cgf.getLoc(memberInit->getSourceLocation()),
118 cgf.getAddrOfLocalVar(args[srcArgIndex]));
119 LValue thisRhslv = cgf.makeNaturalAlignAddrLValue(srcPtr, recordTy);
120 LValue src = cgf.emitLValueForFieldInitialization(thisRhslv, field,
121 field->getName());
122
123 // Copy the aggregate.
124 cgf.emitAggregateCopy(lhs, src, fieldType,
125 cgf.getOverlapForFieldInit(field),
126 lhs.isVolatileQualified());
127 // Ensure that we destroy the objects if an exception is thrown later in
128 // the constructor.
129 assert(!cgf.needsEHCleanup(fieldType.isDestructedType()) &&
130 "Arrays of non-record types shouldn't need EH cleanup");
131 return;
132 }
133 }
134
135 cgf.emitInitializerForField(field, lhs, memberInit->getInit());
136}
137
139 const Type *baseType = baseInit->getBaseClass();
140 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
141 return baseClassDecl->isDynamicClass();
142}
143
144namespace {
145/// Call the destructor for a direct base class.
146struct CallBaseDtor final : EHScopeStack::Cleanup {
147 const CXXRecordDecl *baseClass;
148 bool baseIsVirtual;
149 CallBaseDtor(const CXXRecordDecl *base, bool baseIsVirtual)
150 : baseClass(base), baseIsVirtual(baseIsVirtual) {}
151
152 void emit(CIRGenFunction &cgf, Flags flags) override {
153 const CXXRecordDecl *derivedClass =
154 cast<CXXMethodDecl>(cgf.curFuncDecl)->getParent();
155
156 const CXXDestructorDecl *d = baseClass->getDestructor();
157 // We are already inside a destructor, so presumably the object being
158 // destroyed should have the expected type.
159 QualType thisTy = d->getFunctionObjectParameterType();
160 assert(cgf.currSrcLoc && "expected source location");
161 Address addr = cgf.getAddressOfDirectBaseInCompleteClass(
162 *cgf.currSrcLoc, cgf.loadCXXThisAddress(), derivedClass, baseClass,
163 baseIsVirtual);
164 cgf.emitCXXDestructorCall(d, Dtor_Base, baseIsVirtual,
165 /*delegating=*/false, addr, thisTy);
166 }
167};
168
169/// A visitor which checks whether an initializer uses 'this' in a
170/// way which requires the vtable to be properly set.
171struct DynamicThisUseChecker
172 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
173 using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;
174
175 bool usesThis = false;
176
177 DynamicThisUseChecker(const ASTContext &c) : super(c) {}
178
179 // Black-list all explicit and implicit references to 'this'.
180 //
181 // Do we need to worry about external references to 'this' derived
182 // from arbitrary code? If so, then anything which runs arbitrary
183 // external code might potentially access the vtable.
184 void VisitCXXThisExpr(const CXXThisExpr *e) { usesThis = true; }
185};
186} // end anonymous namespace
187
188static bool baseInitializerUsesThis(ASTContext &c, const Expr *init) {
189 DynamicThisUseChecker checker(c);
190 checker.Visit(init);
191 return checker.usesThis;
192}
193
194/// Gets the address of a direct base class within a complete object.
195/// This should only be used for (1) non-virtual bases or (2) virtual bases
196/// when the type is known to be complete (e.g. in complete destructors).
197///
198/// The object pointed to by 'thisAddr' is assumed to be non-null.
200 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
201 const CXXRecordDecl *base, bool baseIsVirtual) {
202 // 'thisAddr' must be a pointer (in some address space) to Derived.
203 assert(thisAddr.getElementType() == convertType(derived));
204
205 // Compute the offset of the virtual base.
206 CharUnits offset;
207 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
208 if (baseIsVirtual)
209 offset = layout.getVBaseClassOffset(base);
210 else
211 offset = layout.getBaseClassOffset(base);
212
213 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
214 offset.getQuantity(),
215 /*assumeNotNull=*/true);
216}
217
219 const CXXRecordDecl *classDecl,
220 CXXCtorInitializer *baseInit) {
221 assert(curFuncDecl && "loading 'this' without a func declaration?");
223
224 assert(baseInit->isBaseInitializer() && "Must have base initializer!");
225
226 Address thisPtr = loadCXXThisAddress();
227
228 const Type *baseType = baseInit->getBaseClass();
229 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
230
231 bool isBaseVirtual = baseInit->isBaseVirtual();
232
233 // If the initializer for the base (other than the constructor
234 // itself) accesses 'this' in any way, we need to initialize the
235 // vtables.
236 if (baseInitializerUsesThis(getContext(), baseInit->getInit()))
237 initializeVTablePointers(loc, classDecl);
238
239 // We can pretend to be a complete class because it only matters for
240 // virtual bases, and we only do virtual bases for complete ctors.
242 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
246 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
247
248 emitAggExpr(baseInit->getInit(), aggSlot);
249
251}
252
253/// This routine generates necessary code to initialize base classes and
254/// non-static data members belonging to this constructor.
256 CXXCtorType ctorType,
257 FunctionArgList &args) {
258 if (cd->isDelegatingConstructor()) {
260 return;
261 }
262
263 const CXXRecordDecl *classDecl = cd->getParent();
264
265 // Virtual base initializers aren't needed if:
266 // - This is a base ctor variant
267 // - There are no vbases
268 // - The class is abstract, so a complete object of it cannot be constructed
269 //
270 // The check for an abstract class is necessary because sema may not have
271 // marked virtual base destructors referenced.
272 bool constructVBases = ctorType != Ctor_Base &&
273 classDecl->getNumVBases() != 0 &&
274 !classDecl->isAbstract();
275 if (constructVBases &&
276 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
277 cgm.errorNYI(cd->getSourceRange(),
278 "emitCtorPrologue: virtual base without variants");
279 return;
280 }
281
282 // Create three separate ranges for the different types of initializers.
283 auto allInits = cd->inits();
284
285 // Find the boundaries between the three groups.
286 auto virtualBaseEnd = std::find_if(
287 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {
288 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
289 });
290
291 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),
292 [](const CXXCtorInitializer *Init) {
293 return !Init->isBaseInitializer();
294 });
295
296 // Create the three ranges.
297 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);
298 auto nonVirtualBaseInits =
299 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);
300 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());
301
302 const mlir::Value oldThisValue = cxxThisValue;
303
304 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
305 if (cgm.getCodeGenOpts().StrictVTablePointers &&
306 cgm.getCodeGenOpts().OptimizationLevel > 0 &&
307 isInitializerOfDynamicClass(baseInit)) {
308 // It's OK to continue after emitting the error here. The missing code
309 // just "launders" the 'this' pointer.
310 cgm.errorNYI(cd->getSourceRange(),
311 "emitCtorPrologue: strict vtable pointers for vbase");
312 }
313 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
314 };
315
316 // Process virtual base initializers.
317 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
318 if (!constructVBases)
319 continue;
320 emitInitializer(virtualBaseInit);
321 }
322
324
325 // Then, non-virtual base initializers.
326 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
327 assert(!nonVirtualBaseInit->isBaseVirtual());
328 emitInitializer(nonVirtualBaseInit);
329 }
330
331 cxxThisValue = oldThisValue;
332
334
335 // Finally, initialize class members.
337 // Classic codegen uses a special class to attempt to replace member
338 // initializers with memcpy. We could possibly defer that to the
339 // lowering or optimization phases to keep the memory accesses more
340 // explicit. For now, we don't insert memcpy at all.
342 for (CXXCtorInitializer *member : memberInits) {
343 assert(!member->isBaseInitializer());
344 assert(member->isAnyMemberInitializer() &&
345 "Delegating initializer on non-delegating constructor");
346 emitMemberInitializer(*this, cd->getParent(), member, cd, args);
347 }
348}
349
351 mlir::Location loc, CIRGenFunction &cgf, Address addr,
352 CharUnits nonVirtualOffset, mlir::Value virtualOffset,
353 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,
354 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {
355 // Assert that we have something to do.
356 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
357
358 // Compute the offset from the static and dynamic components.
359 mlir::Value baseOffset;
360 if (!nonVirtualOffset.isZero()) {
361 if (virtualOffset) {
362 cgf.cgm.errorNYI(
363 loc,
364 "applyNonVirtualAndVirtualOffset: virtual and non-virtual offset");
365 return Address::invalid();
366 } else {
367 assert(baseValueTy && "expected base type");
368 // If no virtualOffset is present this is the final stop.
369 return cgf.getBuilder().createBaseClassAddr(
370 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),
371 assumeNotNull);
372 }
373 } else {
374 baseOffset = virtualOffset;
375 }
376
377 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,
378 // not bytes. So the pointer must be cast to a byte pointer and back.
379
380 mlir::Value ptr = addr.getPointer();
381 mlir::Type charPtrType = cgf.cgm.uInt8PtrTy;
382 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);
383 mlir::Value adjusted = cir::PtrStrideOp::create(
384 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);
385 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());
386
387 // If we have a virtual component, the alignment of the result will
388 // be relative only to the known alignment of that vbase.
389 CharUnits alignment;
390 if (virtualOffset) {
391 assert(nearestVBase && "virtual offset without vbase?");
392 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,
393 nearestVBase);
394 } else {
395 alignment = addr.getAlignment();
396 }
397 alignment = alignment.alignmentAtOffset(nonVirtualOffset);
398
399 return Address(ptr, alignment);
400}
401
403 const VPtr &vptr) {
404 // Compute the address point.
405 mlir::Value vtableAddressPoint =
406 cgm.getCXXABI().getVTableAddressPointInStructor(
407 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
408
409 if (!vtableAddressPoint)
410 return;
411
412 // Compute where to store the address point.
413 mlir::Value virtualOffset{};
414 CharUnits nonVirtualOffset = CharUnits::Zero();
415
416 mlir::Type baseValueTy;
417 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
418 // We need to use the virtual base offset offset because the virtual base
419 // might have a different offset in the most derived class.
420 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
421 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);
422 nonVirtualOffset = vptr.offsetFromNearestVBase;
423 } else {
424 // We can just use the base offset in the complete class.
425 nonVirtualOffset = vptr.base.getBaseOffset();
426 baseValueTy =
427 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));
428 }
429
430 // Apply the offsets.
431 Address classAddr = loadCXXThisAddress();
432 if (!nonVirtualOffset.isZero() || virtualOffset) {
434 loc, *this, classAddr, nonVirtualOffset, virtualOffset,
435 vptr.vtableClass, vptr.nearestVBase, baseValueTy);
436 }
437
438 // Finally, store the address point. Use the same CIR types as the field.
439 //
440 // vtable field is derived from `this` pointer, therefore they should be in
441 // the same addr space.
443 auto vtablePtr =
444 cir::VTableGetVPtrOp::create(builder, loc, classAddr.getPointer());
445 Address vtableField = Address(vtablePtr, classAddr.getAlignment());
446 builder.createStore(loc, vtableAddressPoint, vtableField);
449}
450
452 const CXXRecordDecl *rd) {
453 // Ignore classes without a vtable.
454 if (!rd->isDynamicClass())
455 return;
456
457 // Initialize the vtable pointers for this class and all of its bases.
458 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
459 for (const auto &vptr : getVTablePointers(rd))
460 initializeVTablePointer(loc, vptr);
461
462 if (rd->getNumVBases())
463 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);
464}
465
468 CIRGenFunction::VPtrsVector vptrsResult;
471 /*NearestVBase=*/nullptr,
472 /*OffsetFromNearestVBase=*/CharUnits::Zero(),
473 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,
474 vptrsResult);
475 return vptrsResult;
476}
477
479 const CXXRecordDecl *nearestVBase,
480 CharUnits offsetFromNearestVBase,
481 bool baseIsNonVirtualPrimaryBase,
482 const CXXRecordDecl *vtableClass,
484 VPtrsVector &vptrs) {
485 // If this base is a non-virtual primary base the address point has already
486 // been set.
487 if (!baseIsNonVirtualPrimaryBase) {
488 // Initialize the vtable pointer for this base.
489 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
490 vptrs.push_back(vptr);
491 }
492
493 const CXXRecordDecl *rd = base.getBase();
494
495 for (const auto &nextBase : rd->bases()) {
496 const auto *baseDecl =
497 cast<CXXRecordDecl>(nextBase.getType()->castAs<RecordType>()->getDecl())
498 ->getDefinitionOrSelf();
499
500 // Ignore classes without a vtable.
501 if (!baseDecl->isDynamicClass())
502 continue;
503
504 CharUnits baseOffset;
505 CharUnits baseOffsetFromNearestVBase;
506 bool baseDeclIsNonVirtualPrimaryBase;
507 const CXXRecordDecl *nextBaseDecl;
508
509 if (nextBase.isVirtual()) {
510 // Check if we've visited this virtual base before.
511 if (!vbases.insert(baseDecl).second)
512 continue;
513
514 const ASTRecordLayout &layout =
515 getContext().getASTRecordLayout(vtableClass);
516
517 nextBaseDecl = baseDecl;
518 baseOffset = layout.getVBaseClassOffset(baseDecl);
519 baseOffsetFromNearestVBase = CharUnits::Zero();
520 baseDeclIsNonVirtualPrimaryBase = false;
521 } else {
522 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
523
524 nextBaseDecl = nearestVBase;
525 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);
526 baseOffsetFromNearestVBase =
527 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);
528 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;
529 }
530
531 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,
532 baseOffsetFromNearestVBase,
533 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,
534 vptrs);
535 }
536}
537
539 assert(curFuncDecl && "loading 'this' without a func declaration?");
541
542 // Lazily compute CXXThisAlignment.
543 if (cxxThisAlignment.isZero()) {
544 // Just use the best known alignment for the parent.
545 // TODO: if we're currently emitting a complete-object ctor/dtor, we can
546 // always use the complete-object alignment.
547 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
548 cxxThisAlignment = cgm.getClassPointerAlignment(rd);
549 }
550
552}
553
555 Expr *init) {
556 QualType fieldType = field->getType();
557 switch (getEvaluationKind(fieldType)) {
558 case cir::TEK_Scalar:
559 if (lhs.isSimple()) {
560 emitExprAsInit(init, field, lhs, false);
561 } else {
562 RValue rhs = RValue::get(emitScalarExpr(init));
563 emitStoreThroughLValue(rhs, lhs);
564 }
565 break;
566 case cir::TEK_Complex:
567 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);
568 break;
569 case cir::TEK_Aggregate: {
575 emitAggExpr(init, slot);
576 break;
577 }
578 }
579
580 // Ensure that we destroy this object if an exception is thrown later in the
581 // constructor.
582 QualType::DestructionKind dtorKind = fieldType.isDestructedType();
583 (void)dtorKind;
585}
586
588 const Expr *e, Address base, mlir::Value memberPtr,
589 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo) {
591
592 cir::GetRuntimeMemberOp op = builder.createGetIndirectMember(
593 getLoc(e->getSourceRange()), base.getPointer(), memberPtr);
594
595 QualType memberType = memberPtrType->getPointeeType();
597 CharUnits memberAlign = cgm.getNaturalTypeAlignment(memberType, baseInfo);
598 memberAlign = cgm.getDynamicOffsetAlignment(
599 base.getAlignment(), memberPtrType->getMostRecentCXXRecordDecl(),
600 memberAlign);
601
602 return Address(op, convertTypeForMem(memberPtrType->getPointeeType()),
603 memberAlign);
604}
605
608 const CXXRecordDecl *baseDecl,
609 CharUnits expectedTargetAlign) {
610 // If the base is an incomplete type (which is, alas, possible with
611 // member pointers), be pessimistic.
612 if (!baseDecl->isCompleteDefinition())
613 return std::min(actualBaseAlign, expectedTargetAlign);
614
615 const ASTRecordLayout &baseLayout =
617 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
618
619 // If the class is properly aligned, assume the target offset is, too.
620 //
621 // This actually isn't necessarily the right thing to do --- if the
622 // class is a complete object, but it's only properly aligned for a
623 // base subobject, then the alignments of things relative to it are
624 // probably off as well. (Note that this requires the alignment of
625 // the target to be greater than the NV alignment of the derived
626 // class.)
627 //
628 // However, our approach to this kind of under-alignment can only
629 // ever be best effort; after all, we're never going to propagate
630 // alignments through variables or parameters. Note, in particular,
631 // that constructing a polymorphic type in an address that's less
632 // than pointer-aligned will generally trap in the constructor,
633 // unless we someday add some sort of attribute to change the
634 // assumed alignment of 'this'. So our goal here is pretty much
635 // just to allow the user to explicitly say that a pointer is
636 // under-aligned and then safely access its fields and vtables.
637 if (actualBaseAlign >= expectedBaseAlign)
638 return expectedTargetAlign;
639
640 // Otherwise, we might be offset by an arbitrary multiple of the
641 // actual alignment. The correct adjustment is to take the min of
642 // the two alignments.
643 return std::min(actualBaseAlign, expectedTargetAlign);
644}
645
646/// Return the best known alignment for a pointer to a virtual base,
647/// given the alignment of a pointer to the derived class.
650 const CXXRecordDecl *derivedClass,
651 const CXXRecordDecl *vbaseClass) {
652 // The basic idea here is that an underaligned derived pointer might
653 // indicate an underaligned base pointer.
654
655 assert(vbaseClass->isCompleteDefinition());
656 const ASTRecordLayout &baseLayout =
657 getASTContext().getASTRecordLayout(vbaseClass);
658 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
659
660 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
661 expectedVBaseAlign);
662}
663
664/// Emit a loop to call a particular constructor for each of several members
665/// of an array.
666///
667/// \param ctor the constructor to call for each element
668/// \param arrayType the type of the array to initialize
669/// \param arrayBegin an arrayType*
670/// \param zeroInitialize true if each element should be
671/// zero-initialized before it is constructed
674 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
675 bool zeroInitialize) {
676 QualType elementType;
677 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
678 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
679 newPointerIsChecked, zeroInitialize);
680}
681
682/// Emit a loop to call a particular constructor for each of several members
683/// of an array.
684///
685/// \param ctor the constructor to call for each element
686/// \param numElements the number of elements in the array;
687/// may be zero
688/// \param arrayBase a T*, where T is the type constructed by ctor
689/// \param zeroInitialize true if each element should be
690/// zero-initialized before it is constructed
692 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
693 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize) {
694 // It's legal for numElements to be zero. This can happen both
695 // dynamically, because x can be zero in 'new A[x]', and statically,
696 // because of GCC extensions that permit zero-length arrays. There
697 // are probably legitimate places where we could assume that this
698 // doesn't happen, but it's not clear that it's worth it.
699
700 auto arrayTy = mlir::cast<cir::ArrayType>(arrayBase.getElementType());
701 mlir::Type elementType = arrayTy.getElementType();
702
703 // This might be a multi-dimensional array. Find the innermost element type.
704 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
705 elementType = maybeArrayTy.getElementType();
706 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
707
708 // Optimize for a constant count.
709 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
710 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>()) {
711 // Just skip out if the constant count is zero.
712 if (constIntAttr.getUInt() == 0)
713 return;
714
715 arrayTy = cir::ArrayType::get(elementType, constIntAttr.getUInt());
716 // Otherwise, emit the check.
717 }
718
719 if (constantCount.use_empty())
720 constantCount.erase();
721 } else {
722 // Otherwise, emit the check.
723 cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");
724 }
725
726 // Tradional LLVM codegen emits a loop here. CIR lowers to a loop as part of
727 // LoweringPrepare.
728
729 // The alignment of the base, adjusted by the size of a single element,
730 // provides a conservative estimate of the alignment of every element.
731 // (This assumes we never start tracking offsetted alignments.)
732 //
733 // Note that these are complete objects and so we don't need to
734 // use the non-virtual size or alignment.
736 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
737 getContext().getTypeSizeInChars(type));
738
739 // Zero initialize the storage, if requested.
740 if (zeroInitialize)
742
743 // C++ [class.temporary]p4:
744 // There are two contexts in which temporaries are destroyed at a different
745 // point than the end of the full-expression. The first context is when a
746 // default constructor is called to initialize an element of an array.
747 // If the constructor has one or more default arguments, the destruction of
748 // every temporary created in a default argument expression is sequenced
749 // before the construction of the next array element, if any.
750 {
751 RunCleanupsScope scope(*this);
752
753 // Evaluate the constructor and its arguments in a regular
754 // partial-destroy cleanup.
755 if (getLangOpts().Exceptions &&
756 !ctor->getParent()->hasTrivialDestructor()) {
757 cgm.errorNYI(e->getSourceRange(), "partial array cleanups");
758 }
759
760 // Emit the constructor call that will execute for every array element.
761 mlir::Value arrayOp =
762 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
763 cir::ArrayCtor::create(
764 builder, *currSrcLoc, arrayOp,
765 [&](mlir::OpBuilder &b, mlir::Location loc) {
766 mlir::BlockArgument arg =
767 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
768 Address curAddr = Address(arg, elementType, eltAlignment);
770 auto currAVS = AggValueSlot::forAddr(
771 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
775 /*ForVirtualBase=*/false,
776 /*Delegating=*/false, currAVS, e);
777 cir::YieldOp::create(builder, loc);
778 });
779 }
780}
781
783 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
784 const FunctionArgList &args, SourceLocation loc) {
785 CallArgList delegateArgs;
786
787 FunctionArgList::const_iterator i = args.begin(), e = args.end();
788 assert(i != e && "no parameters to constructor");
789
790 // this
791 Address thisAddr = loadCXXThisAddress();
792 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
793 ++i;
794
795 // FIXME: The location of the VTT parameter in the parameter list is specific
796 // to the Itanium ABI and shouldn't be hardcoded here.
797 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
798 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
799 return;
800 }
801
802 // Explicit arguments.
803 for (; i != e; ++i) {
804 const VarDecl *param = *i;
805 // FIXME: per-argument source location
806 emitDelegateCallArg(delegateArgs, param, loc);
807 }
808
810
811 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
812 /*Delegating=*/true, thisAddr, delegateArgs, loc);
813}
814
816 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
817 assert(assignOp->isCopyAssignmentOperator() ||
818 assignOp->isMoveAssignmentOperator());
819 const Stmt *rootS = assignOp->getBody();
820 assert(isa<CompoundStmt>(rootS) &&
821 "Body of an implicit assignment operator should be compound stmt.");
822 const auto *rootCS = cast<CompoundStmt>(rootS);
823
824 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), assignOp);
825
828
829 // Classic codegen uses a special class to attempt to replace member
830 // initializers with memcpy. We could possibly defer that to the
831 // lowering or optimization phases to keep the memory accesses more
832 // explicit. For now, we don't insert memcpy at all, though in some
833 // cases the AST contains a call to memcpy.
835 for (Stmt *s : rootCS->body())
836 if (emitStmt(s, /*useCurrentScope=*/true).failed())
837 cgm.errorNYI(s->getSourceRange(),
838 std::string("emitImplicitAssignmentOperatorBody: ") +
839 s->getStmtClassName());
840}
841
843 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
844 // Get the address of the call operator.
845 const CIRGenFunctionInfo &calleeFnInfo =
846 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
847 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
848 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
849
850 // Prepare the return slot.
851 const FunctionProtoType *fpt =
852 callOperator->getType()->castAs<FunctionProtoType>();
853 QualType resultType = fpt->getReturnType();
854 ReturnValueSlot returnSlot;
855
856 // We don't need to separately arrange the call arguments because
857 // the call can't be variadic anyway --- it's impossible to forward
858 // variadic arguments.
859
860 // Now emit our call.
861 CIRGenCallee callee =
862 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
863 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs);
864
865 // If necessary, copy the returned value into the slot.
866 if (!resultType->isVoidType() && returnSlot.isNull()) {
867 if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType())
868 cgm.errorNYI(callOperator->getSourceRange(),
869 "emitForwardingCallToLambda: ObjCAutoRefCount");
870 emitReturnOfRValue(*currSrcLoc, rv, resultType);
871 } else {
872 cgm.errorNYI(callOperator->getSourceRange(),
873 "emitForwardingCallToLambda: return slot is not null");
874 }
875}
876
878 const CXXRecordDecl *lambda = md->getParent();
879
880 // Start building arguments for forwarding call
881 CallArgList callArgs;
882
883 QualType lambdaType = getContext().getCanonicalTagType(lambda);
884 QualType thisType = getContext().getPointerType(lambdaType);
885 Address thisPtr =
886 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");
887 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);
888
889 // Add the rest of the parameters.
890 for (auto *param : md->parameters())
891 emitDelegateCallArg(callArgs, param, param->getBeginLoc());
892
893 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();
894 // For a generic lambda, find the corresponding call operator specialization
895 // to which the call to the static-invoker shall be forwarded.
896 if (lambda->isGenericLambda()) {
899 FunctionTemplateDecl *callOpTemplate =
901 void *InsertPos = nullptr;
902 FunctionDecl *correspondingCallOpSpecialization =
903 callOpTemplate->findSpecialization(tal->asArray(), InsertPos);
904 assert(correspondingCallOpSpecialization);
905 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
906 }
907 emitForwardingCallToLambda(callOp, callArgs);
908}
909
911 if (md->isVariadic()) {
912 // Codgen for LLVM doesn't emit code for this as well, it says:
913 // FIXME: Making this work correctly is nasty because it requires either
914 // cloning the body of the call operator or making the call operator
915 // forward.
916 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");
917 }
918
920}
921
923 QualType type) {
924 const auto *record = type->castAsCXXRecordDecl();
925 const CXXDestructorDecl *dtor = record->getDestructor();
926 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
927 // dtors which shall be removed on later CIR passes. However, only remove this
928 // assertion after we have a test case to exercise this path.
929 assert(!dtor->isTrivial());
930 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
931 /*delegating=*/false, addr, type);
932}
933
934namespace {
935mlir::Value loadThisForDtorDelete(CIRGenFunction &cgf,
936 const CXXDestructorDecl *dd) {
937 if (Expr *thisArg = dd->getOperatorDeleteThisArg())
938 return cgf.emitScalarExpr(thisArg);
939 return cgf.loadCXXThis();
940}
941
942/// Call the operator delete associated with the current destructor.
943struct CallDtorDelete final : EHScopeStack::Cleanup {
944 CallDtorDelete() {}
945
946 void emit(CIRGenFunction &cgf, Flags flags) override {
947 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(cgf.curFuncDecl);
948 const CXXRecordDecl *classDecl = dtor->getParent();
950 loadThisForDtorDelete(cgf, dtor),
951 cgf.getContext().getCanonicalTagType(classDecl));
952 }
953};
954
955class DestroyField final : public EHScopeStack::Cleanup {
956 const FieldDecl *field;
957 CIRGenFunction::Destroyer *destroyer;
958
959public:
960 DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
961 : field(field), destroyer(destroyer) {}
962
963 void emit(CIRGenFunction &cgf, Flags flags) override {
964 // Find the address of the field.
965 Address thisValue = cgf.loadCXXThisAddress();
966 CanQualType recordTy =
967 cgf.getContext().getCanonicalTagType(field->getParent());
968 LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);
969 LValue lv = cgf.emitLValueForField(thisLV, field);
970 assert(lv.isSimple());
971
973 cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);
974 }
975};
976} // namespace
977
978/// Emit all code that comes at the end of class's destructor. This is to call
979/// destructors on members and base classes in reverse order of their
980/// construction.
981///
982/// For a deleting destructor, this also handles the case where a destroying
983/// operator delete completely overrides the definition.
985 CXXDtorType dtorType) {
986 assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&
987 "Should not emit dtor epilogue for non-exported trivial dtor!");
988
989 // The deleting-destructor phase just needs to call the appropriate
990 // operator delete that Sema picked up.
991 if (dtorType == Dtor_Deleting) {
992 assert(dd->getOperatorDelete() &&
993 "operator delete missing - EnterDtorCleanups");
995 cgm.errorNYI(dd->getSourceRange(), "deleting destructor with vtt");
996 } else {
998 cgm.errorNYI(dd->getSourceRange(),
999 "deleting destructor with destroying operator delete");
1000 } else {
1001 ehStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
1002 }
1003 }
1004 return;
1005 }
1006
1007 const CXXRecordDecl *classDecl = dd->getParent();
1008
1009 // Unions have no bases and do not call field destructors.
1010 if (classDecl->isUnion())
1011 return;
1012
1013 // The complete-destructor phase just destructs all the virtual bases.
1014 if (dtorType == Dtor_Complete) {
1016
1017 // We push them in the forward order so that they'll be popped in
1018 // the reverse order.
1019 for (const CXXBaseSpecifier &base : classDecl->vbases()) {
1020 auto *baseClassDecl = base.getType()->castAsCXXRecordDecl();
1021
1022 if (baseClassDecl->hasTrivialDestructor()) {
1023 // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
1024 // memory. For non-trival base classes the same is done in the class
1025 // destructor.
1027 } else {
1028 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1029 /*baseIsVirtual=*/true);
1030 }
1031 }
1032
1033 return;
1034 }
1035
1036 assert(dtorType == Dtor_Base);
1038
1039 // Destroy non-virtual bases.
1040 for (const CXXBaseSpecifier &base : classDecl->bases()) {
1041 // Ignore virtual bases.
1042 if (base.isVirtual())
1043 continue;
1044
1045 CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();
1046
1047 if (baseClassDecl->hasTrivialDestructor())
1049 else
1050 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1051 /*baseIsVirtual=*/false);
1052 }
1053
1055
1056 // Destroy direct fields.
1057 for (const FieldDecl *field : classDecl->fields()) {
1058 QualType type = field->getType();
1059 QualType::DestructionKind dtorKind = type.isDestructedType();
1060 if (!dtorKind)
1061 continue;
1062
1063 // Anonymous union members do not have their destructors called.
1064 const RecordType *rt = type->getAsUnionType();
1065 if (rt && rt->getDecl()->isAnonymousStructOrUnion())
1066 continue;
1067
1068 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1070 ehStack.pushCleanup<DestroyField>(cleanupKind, field,
1071 getDestroyer(dtorKind));
1072 }
1073}
1074
1076 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
1077 assert(ctor->isDelegatingConstructor());
1078
1079 Address thisPtr = loadCXXThisAddress();
1080
1087
1088 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
1089
1090 const CXXRecordDecl *classDecl = ctor->getParent();
1091 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
1092 cgm.errorNYI(ctor->getSourceRange(),
1093 "emitDelegatingCXXConstructorCall: exception");
1094 return;
1095 }
1096}
1097
1100 bool forVirtualBase, bool delegating,
1101 Address thisAddr, QualType thisTy) {
1102 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
1103 delegating, thisAddr, thisTy);
1104}
1105
1106mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1107 bool delegating) {
1108 if (!cgm.getCXXABI().needsVTTParameter(gd))
1109 return nullptr;
1110
1111 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
1112 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();
1113
1114 uint64_t subVTTIndex;
1115
1116 if (delegating) {
1117 // If this is a delegating constructor call, just load the VTT.
1118 return loadCXXVTT();
1119 } else if (rd == base) {
1120 // If the record matches the base, this is the complete ctor/dtor
1121 // variant calling the base variant in a class with virtual bases.
1122 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
1123 "doing no-op VTT offset in base dtor/ctor?");
1124 assert(!forVirtualBase && "Can't have same class as virtual base!");
1125 subVTTIndex = 0;
1126 } else {
1127 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1128 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)
1129 : layout.getBaseClassOffset(base);
1130
1131 subVTTIndex =
1132 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));
1133 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
1134 }
1135
1136 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
1137 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
1138 // A VTT parameter was passed to the constructor, use it.
1139 mlir::Value vtt = loadCXXVTT();
1140 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
1141 } else {
1142 // We're the complete constructor, so get the VTT by name.
1143 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);
1144 return builder.createVTTAddrPoint(
1145 loc, builder.getPointerTo(cgm.voidPtrTy),
1146 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);
1147 }
1148}
1149
1151 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1152 llvm::iterator_range<CastExpr::path_const_iterator> path,
1153 bool nullCheckValue) {
1154 assert(!path.empty() && "Base path should not be empty!");
1155
1156 QualType derivedTy = getContext().getCanonicalTagType(derived);
1157 mlir::Type derivedValueTy = convertType(derivedTy);
1158 CharUnits nonVirtualOffset =
1159 cgm.computeNonVirtualBaseClassOffset(derived, path);
1160
1161 // Note that in OG, no offset (nonVirtualOffset.getQuantity() == 0) means it
1162 // just gives the address back. In CIR a `cir.derived_class` is created and
1163 // made into a nop later on during lowering.
1164 return builder.createDerivedClassAddr(loc, baseAddr, derivedValueTy,
1165 nonVirtualOffset.getQuantity(),
1166 /*assumeNotNull=*/!nullCheckValue);
1167}
1168
1170 Address value, const CXXRecordDecl *derived,
1171 llvm::iterator_range<CastExpr::path_const_iterator> path,
1172 bool nullCheckValue, SourceLocation loc) {
1173 assert(!path.empty() && "Base path should not be empty!");
1174
1175 CastExpr::path_const_iterator start = path.begin();
1176 const CXXRecordDecl *vBase = nullptr;
1177
1178 if ((*path.begin())->isVirtual()) {
1179 vBase = (*start)->getType()->castAsCXXRecordDecl();
1180 ++start;
1181 }
1182
1183 // Compute the static offset of the ultimate destination within its
1184 // allocating subobject (the virtual base, if there is one, or else
1185 // the "complete" object that we see).
1186 CharUnits nonVirtualOffset = cgm.computeNonVirtualBaseClassOffset(
1187 vBase ? vBase : derived, {start, path.end()});
1188
1189 // If there's a virtual step, we can sometimes "devirtualize" it.
1190 // For now, that's limited to when the derived type is final.
1191 // TODO: "devirtualize" this for accesses to known-complete objects.
1192 if (vBase && derived->hasAttr<FinalAttr>()) {
1193 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
1194 CharUnits vBaseOffset = layout.getVBaseClassOffset(vBase);
1195 nonVirtualOffset += vBaseOffset;
1196 vBase = nullptr; // we no longer have a virtual step
1197 }
1198
1199 // Get the base pointer type.
1200 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
1202
1203 // If there is no virtual base, use cir.base_class_addr. It takes care of
1204 // the adjustment and the null pointer check.
1205 if (nonVirtualOffset.isZero() && !vBase) {
1207 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
1208 /*assumeNotNull=*/true);
1209 }
1210
1212
1213 // Compute the virtual offset.
1214 mlir::Value virtualOffset = nullptr;
1215 if (vBase) {
1216 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
1217 getLoc(loc), *this, value, derived, vBase);
1218 }
1219
1220 // Apply both offsets.
1222 getLoc(loc), *this, value, nonVirtualOffset, virtualOffset, derived,
1223 vBase, baseValueTy, not nullCheckValue);
1224
1225 // Cast to the destination type.
1226 value = value.withElementType(builder, baseValueTy);
1227
1228 return value;
1229}
1230
1231// TODO(cir): this can be shared with LLVM codegen.
1234 if (!cgm.getCodeGenOpts().WholeProgramVTables)
1235 return false;
1236
1237 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1238 return true;
1239
1241
1242 return false;
1243}
1244
1245mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1246 const CXXRecordDecl *rd) {
1247 auto vtablePtr =
1248 cir::VTableGetVPtrOp::create(builder, loc, thisAddr.getPointer());
1249 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1250
1251 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1253
1254 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1255 cgm.getCodeGenOpts().StrictVTablePointers) {
1257 }
1258
1259 return vtable;
1260}
1261
1264 bool forVirtualBase,
1265 bool delegating,
1266 AggValueSlot thisAVS,
1267 const clang::CXXConstructExpr *e) {
1268 CallArgList args;
1269 Address thisAddr = thisAVS.getAddress();
1270 QualType thisType = d->getThisType();
1271 mlir::Value thisPtr = thisAddr.getPointer();
1272
1274
1275 args.add(RValue::get(thisPtr), thisType);
1276
1277 // In LLVM Codegen: If this is a trivial constructor, just emit what's needed.
1278 // If this is a union copy constructor, we must emit a memcpy, because the AST
1279 // does not model that copy.
1281
1282 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1283
1285
1286 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1287 /*ParamsToSkip=*/0);
1288
1290 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1291 e->getExprLoc());
1292}
1293
1295 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1296 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1297
1298 const CXXRecordDecl *crd = d->getParent();
1299
1300 // If this is a call to a trivial default constructor:
1301 // In LLVM: do nothing.
1302 // In CIR: emit as a regular call, other later passes should lower the
1303 // ctor call into trivial initialization.
1305
1307
1308 bool passPrototypeArgs = true;
1309
1310 // Check whether we can actually emit the constructor before trying to do so.
1311 if (d->getInheritedConstructor()) {
1312 cgm.errorNYI(d->getSourceRange(),
1313 "emitCXXConstructorCall: inherited constructor");
1314 return;
1315 }
1316
1317 // Insert any ABI-specific implicit constructor arguments.
1319 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1320 delegating, args);
1321
1322 // Emit the call.
1323 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1324 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1325 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1326 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1327 cir::CIRCallOpInterface c;
1328 emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
1329
1330 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1331 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1332 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1333}
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 bool baseInitializerUsesThis(ASTContext &c, const Expr *init)
static Address applyNonVirtualAndVirtualOffset(mlir::Location loc, CIRGenFunction &cgf, Address addr, CharUnits nonVirtualOffset, mlir::Value virtualOffset, const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase, mlir::Type baseValueTy={}, bool assumeNotNull=true)
static void emitMemberInitializer(CIRGenFunction &cgf, const CXXRecordDecl *classDecl, CXXCtorInitializer *memberInit, const CXXConstructorDecl *constructor, FunctionArgList &args)
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit)
static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf, CXXCtorInitializer *memberInit, LValue &lhs)
Defines the clang::Expr interface and subclasses for C++ expressions.
C Language Family Type Representation.
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3723
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
mlir::Value getPointer() const
Definition Address.h:90
mlir::Type getElementType() const
Definition Address.h:117
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.
clang::CharUnits getAlignment() const
Definition Address.h:130
An aggregate value slot.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Address createBaseClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &args) const =0
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:90
A scope within which we are constructing the fields of an object which might use a CXXDefaultInitExpr...
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md)
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...
Address emitCXXMemberDataPointerAddress(const Expr *e, Address base, mlir::Value memberPtr, const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo)
const clang::LangOptions & getLangOpts() const
void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator, CallArgList &callArgs)
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
const clang::Decl * curFuncDecl
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void initializeVTablePointers(mlir::Location loc, const clang::CXXRecordDecl *rd)
void initializeVTablePointer(mlir::Location loc, const VPtr &vptr)
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl, CXXCtorInitializer *baseInit)
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
mlir::Type convertTypeForMem(QualType t)
void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args)
This routine generates necessary code to initialize base classes and non-static data members belongin...
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
llvm::SmallPtrSet< const clang::CXXRecordDecl *, 4 > VisitedVirtualBasesSetTy
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
void emitInitializerForField(clang::FieldDecl *field, LValue lhs, clang::Expr *init)
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
CIRGenBuilderTy & getBuilder()
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
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)
llvm::SmallVector< VPtr, 4 > VPtrsVector
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
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.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitDelegatingCXXConstructorCall(const CXXConstructorDecl *ctor, const FunctionArgList &args)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign, const CXXRecordDecl *baseDecl, CharUnits expectedTargetAlign)
TODO: Add TBAAAccessInfo.
CharUnits getVBaseAlignment(CharUnits derivedAlign, const CXXRecordDecl *derived, const CXXRecordDecl *vbase)
Returns the assumed alignment of a virtual base of a class.
CIRGenCXXABI & getCXXABI() const
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:233
Information for lazily generating a cleanup.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:191
bool isSimple() const
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
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 base class of a C++ class.
Definition DeclCXX.h:146
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
arg_range arguments()
Definition ExprCXX.h:1672
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1611
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
init_iterator init_begin()
Retrieve an iterator to the first initializer.
Definition DeclCXX.h:2701
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
Definition DeclCXX.h:2757
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Definition DeclCXX.cpp:3019
InheritedConstructor getInheritedConstructor() const
Get the constructor that this inheriting constructor is based on.
Definition DeclCXX.h:2842
Represents a C++ base or member initializer.
Definition DeclCXX.h:2369
Expr * getInit() const
Get the initializer.
Definition DeclCXX.h:2571
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
Definition DeclCXX.cpp:2903
bool isAnyMemberInitializer() const
Definition DeclCXX.h:2449
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Definition DeclCXX.h:2441
bool isIndirectMemberInitializer() const
Definition DeclCXX.h:2453
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Definition DeclCXX.cpp:2896
FieldDecl * getAnyMember() const
Definition DeclCXX.h:2515
IndirectFieldDecl * getIndirectMember() const
Definition DeclCXX.h:2523
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Definition DeclCXX.h:2495
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
const FunctionDecl * getOperatorDelete() const
Definition DeclCXX.cpp:3170
Expr * getOperatorDeleteThisArg() const
Definition DeclCXX.h:2908
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
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
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2809
QualType getFunctionObjectParameterType() const
Definition DeclCXX.h:2279
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
Definition DeclCXX.cpp:1673
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1366
base_class_range bases()
Definition DeclCXX.h:608
base_class_range vbases()
Definition DeclCXX.h:625
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1221
bool isDynamicClass() const
Definition DeclCXX.h:574
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition DeclCXX.cpp:1736
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
const CXXBaseSpecifier *const * path_const_iterator
Definition Expr.h:3677
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition CharUnits.h:214
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:3761
bool hasAttr() const
Definition DeclBase.h:577
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
Represents a member of a struct/union/class.
Definition Decl.h:3160
Represents a function declaration or definition.
Definition Decl.h:2000
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4201
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4189
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3547
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3129
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4325
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:4545
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5269
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5673
Declaration of a template function.
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
QualType getReturnType() const
Definition TypeBase.h:4805
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
CXXCtorType getCtorType() const
Definition GlobalDecl.h:108
const Decl * getDecl() const
Definition GlobalDecl.h:106
Represents a field injected from an anonymous union/struct into the parent scope.
Definition Decl.h:3467
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3488
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3654
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5449
QualType getPointeeType() const
Definition TypeBase.h:3672
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
A (possibly-)qualified type.
Definition TypeBase.h:937
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1545
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
field_range fields() const
Definition Decl.h:4524
Encodes a location in the source.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3812
bool isUnion() const
Definition Decl.h:3922
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3547
The base class of the type hierarchy.
Definition TypeBase.h:1833
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9179
bool isRecordType() const
Definition TypeBase.h:8657
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
#define not
Definition iso646.h:22
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
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
CXXDtorType
C++ destructor types.
Definition ABI.h:34
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool addressSpace()
static bool useEHCleanupForArray()
static bool aggValueSlotGC()
static bool isMemcpyEquivalentSpecialMember()
static bool hiddenVisibility()
static bool runCleanupsScope()
static bool opCallArgEvaluationOrder()
static bool createInvariantGroup()
static bool isTrivialCtorOrDtor()
static bool assignMemcpyizer()
static bool ctorMemcpyizer()
static bool requiresCleanups()
static bool generateDebugInfo()
static bool incrementProfileCounter()
Similar to AddedStructorArgs, but only notes the number of additional arguments.
const clang::CXXRecordDecl * vtableClass
const clang::CXXRecordDecl * nearestVBase