Lines Matching +full:entry +full:- +full:method

1 //===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
33 /// BaseOffset - Represents an offset from a derived class to a direct or
36 /// DerivedClass - The derived class.
39 /// VirtualBase - If the path from the derived class to the base class
44 /// NonVirtualOffset - The offset from the derived class to the base class.
60 /// FinalOverriders - Contains the final overrider member functions for all
64 /// OverriderInfo - Information about a final overrider.
66 /// Method - The method decl of the overrider.
67 const CXXMethodDecl *Method; member
69 /// VirtualBase - The virtual base class subobject of this overrider.
73 /// Offset - the base offset of the overrider's parent in the layout class.
76 OverriderInfo() : Method(nullptr), VirtualBase(nullptr), in OverriderInfo()
81 /// MostDerivedClass - The most derived class for which the final overriders
85 /// MostDerivedClassOffset - If we're building final overriders for a
90 /// LayoutClass - The class we're using for layout information. Will be
97 /// MostDerivedClassLayout - the AST record layout of the most derived class.
100 /// MethodBaseOffsetPairTy - Uniquely identifies a member function
107 /// OverridersMap - The final overriders for all virtual member functions of
111 /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
119 /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
129 /// dump - dump the final overriders for a base subobject, and all its direct
139 /// getOverrider - Get the final overrider for the given method declaration in
149 /// dump - dump the final overriders.
163 Context(MostDerivedClass->getASTContext()), in FinalOverriders()
178 MostDerivedClass->getFinalOverriders(FinalOverriders); in FinalOverriders()
186 assert(SubobjectOffsets.count(std::make_pair(MD->getParent(), in FinalOverriders()
190 CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(), in FinalOverriders()
194 const UniqueVirtualMethod &Method = M.second.front(); in FinalOverriders() local
196 const CXXRecordDecl *OverriderRD = Method.Method->getParent(); in FinalOverriders()
198 std::make_pair(OverriderRD, Method.Subobject)) in FinalOverriders()
202 Method.Subobject)]; in FinalOverriders()
205 assert(!Overrider.Method && "Overrider should not exist yet!"); in FinalOverriders()
208 Overrider.Method = Method.Method; in FinalOverriders()
209 Overrider.VirtualBase = Method.InVirtualSubobject; in FinalOverriders()
228 for (int I = Path.size(), E = 0; I != E; --I) { in ComputeBaseOffset()
229 const CXXBasePathElement &Element = Path[I - 1]; in ComputeBaseOffset()
231 if (Element.Base->isVirtual()) { in ComputeBaseOffset()
233 QualType VBaseType = Element.Base->getType(); in ComputeBaseOffset()
234 VirtualBase = VBaseType->getAsCXXRecordDecl(); in ComputeBaseOffset()
239 // Now compute the non-virtual offset. in ComputeBaseOffset()
246 const CXXRecordDecl *Base = Element.Base->getType()->getAsCXXRecordDecl(); in ComputeBaseOffset()
264 if (!DerivedRD->isDerivedFrom(BaseRD, Paths)) in ComputeBaseOffset()
274 const auto *BaseFT = BaseMD->getType()->castAs<FunctionType>(); in ComputeReturnAdjustmentBaseOffset()
275 const auto *DerivedFT = DerivedMD->getType()->castAs<FunctionType>(); in ComputeReturnAdjustmentBaseOffset()
279 Context.getCanonicalType(DerivedFT->getReturnType()); in ComputeReturnAdjustmentBaseOffset()
281 Context.getCanonicalType(BaseFT->getReturnType()); in ComputeReturnAdjustmentBaseOffset()
283 assert(CanDerivedReturnType->getTypeClass() == in ComputeReturnAdjustmentBaseOffset()
284 CanBaseReturnType->getTypeClass() && in ComputeReturnAdjustmentBaseOffset()
294 CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType(); in ComputeReturnAdjustmentBaseOffset()
296 CanBaseReturnType->getAs<ReferenceType>()->getPointeeType(); in ComputeReturnAdjustmentBaseOffset()
299 CanDerivedReturnType->getAs<PointerType>()->getPointeeType(); in ComputeReturnAdjustmentBaseOffset()
301 CanBaseReturnType->getAs<PointerType>()->getPointeeType(); in ComputeReturnAdjustmentBaseOffset()
316 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl()); in ComputeReturnAdjustmentBaseOffset()
319 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl()); in ComputeReturnAdjustmentBaseOffset()
347 for (const auto &B : RD->bases()) { in ComputeBaseOffsets()
348 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in ComputeBaseOffsets()
383 for (const auto &B : RD->bases()) { in dump()
384 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in dump()
387 if (!BaseDecl->isPolymorphic()) in dump()
406 RD->printQualifiedName(Out); in dump()
411 for (const auto *MD : RD->methods()) { in dump()
414 MD = MD->getCanonicalDecl(); in dump()
419 MD->printQualifiedName(Out); in dump()
420 Out << " - ("; in dump()
421 Overrider.Method->printQualifiedName(Out); in dump()
425 if (!Overrider.Method->isPureVirtual()) in dump()
426 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD); in dump()
429 Out << " [ret-adj: "; in dump()
431 Offset.VirtualBase->printQualifiedName(Out); in dump()
442 /// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
447 /// Offsets - Keeps track of methods and their offsets.
451 /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
457 /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
462 /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
466 // empty - Return whether the offset map is empty or not.
473 cast<FunctionProtoType>(LHS->getType().getCanonicalType()); in HasSameVirtualSignature()
475 cast<FunctionProtoType>(RHS->getType().getCanonicalType()); in HasSameVirtualSignature()
477 // Fast-path matches in the canonical types. in HasSameVirtualSignature()
483 if (LT->getMethodQuals() != RT->getMethodQuals()) in HasSameVirtualSignature()
485 return LT->getParamTypes() == RT->getParamTypes(); in HasSameVirtualSignature()
500 DeclarationName LHSName = LHS->getDeclName(); in MethodsCanShareVCallOffset()
501 DeclarationName RHSName = RHS->getDeclName(); in MethodsCanShareVCallOffset()
532 /// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
541 /// MostDerivedClass - The most derived class for which we're building vcall
545 /// LayoutClass - The class we're using for layout information. Will be
550 /// Context - The ASTContext which we will use for layout information.
553 /// Components - vcall and vbase offset components
557 /// VisitedVirtualBases - Visited virtual bases.
560 /// VCallOffsets - Keeps track of vcall offsets.
564 /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
568 /// FinalOverriders - The final overriders of the most derived class.
572 /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
577 /// AddVCallOffsets - Add vcall offsets for the given base subobject.
580 /// AddVBaseOffsets - Add vbase offsets for the given class.
584 /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
596 LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), in VCallAndVBaseOffsetBuilder()
670 NumComponentsAboveAddrPoint--; in getCurrentOffsetOffset()
672 -(int64_t)(NumComponentsAboveAddrPoint + Components.size()); in getCurrentOffsetOffset()
674 // Under the relative ABI, the offset widths are 32-bit ints instead of in getCurrentOffsetOffset()
693 // We only want to add vcall offsets if the base is non-virtual; a virtual in AddVCallOffsets()
705 for (const auto *MD : RD->methods()) { in AddVCallOffsets()
708 MD = MD->getCanonicalDecl(); in AddVCallOffsets()
722 Overriders->getOverrider(MD, Base.getBaseOffset()); in AddVCallOffsets()
726 Offset = Overrider.Offset - VBaseOffset; in AddVCallOffsets()
733 // And iterate over all non-virtual bases (ignoring the primary base). in AddVCallOffsets()
734 for (const auto &B : RD->bases()) { in AddVCallOffsets()
738 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in AddVCallOffsets()
758 for (const auto &B : RD->bases()) { in AddVBaseOffsets()
759 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in AddVBaseOffsets()
764 LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass; in AddVBaseOffsets()
783 /// ItaniumVTableBuilder - Class for building vtable layout information.
786 /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
799 /// VTables - Global vtable information.
802 /// MostDerivedClass - The most derived class for which we're building this
806 /// MostDerivedClassOffset - If we're building a construction vtable, this
810 /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
814 /// LayoutClass - The class we're using for layout information. Will be
819 /// Context - The ASTContext which we will use for layout information.
822 /// FinalOverriders - The final overriders of the most derived class.
825 /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
829 /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
833 /// Components - The components of the vtable being built.
836 /// AddressPoints - Address points for the vtable being built.
839 /// MethodInfo - Contains information about a method in a vtable.
842 /// BaseOffset - The base offset of this method.
845 /// BaseOffsetInLayoutClass - The base offset in the layout class of this
846 /// method.
849 /// VTableIndex - The index in the vtable that this method has.
869 /// MethodInfoMap - The information for all methods in the vtable we're
873 /// MethodVTableIndices - Contains the index (relative to the vtable address
879 /// VTableThunks - The thunks by vtable index in the vtable currently being
886 /// Thunks - A map that contains all the thunks needed for all methods in the
890 /// AddThunk - Add a thunk for the given method.
893 /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
899 /// PrimaryVirtualBases - All known virtual bases who are a primary base of
903 /// ComputeReturnAdjustment - Compute the return adjustment given a return
907 /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
912 /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
920 /// AddMethod - Add a single virtual member function to the vtable
924 /// IsOverriderUsed - Returns whether the overrider will ever be used in this
935 /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
939 /// to adjust this from C* to B::A*, which would require a third-party
941 /// C-in-D's copy of A's vtable is never referenced, so this is not
949 /// AddMethods - Add the methods of this base subobject and all its
956 // LayoutVTable - Layout the vtable for the given base class, including its
960 /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
966 /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
973 /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
981 /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
987 /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
992 /// isBuildingConstructionVTable - Return whether this vtable builder is
1011 LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), in ItaniumVTableBuilder()
1067 /// dumpLayout - Dump the vtable layout.
1087 /// Visit all the methods overridden by the given method recursively,
1088 /// in a depth-first pre-order. The Visitor's visitor method returns a bool
1090 /// method (i.e. returning false stops the iteration).
1094 assert(VTableContextBase::hasVtableSlot(MD) && "Method is not virtual!"); in visitAllOverriddenMethods()
1096 for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) { in visitAllOverriddenMethods()
1103 /// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
1109 // Don't recurse on this method if we've already collected it. in ComputeAllOverriddenMethods()
1116 // Now go through the method info map and see if any of the methods need in ComputeThisAdjustments()
1128 // Get the final overrider for this method. in ComputeThisAdjustments()
1151 // If a this pointer adjustment is required, record the method that in ComputeThisAdjustments()
1152 // created the vtable entry. MD is not necessarily the method that in ComputeThisAdjustments()
1153 // created the entry since derived classes overwrite base class in ComputeThisAdjustments()
1158 // Overrider = D2:m, the original method that created the entry is B0:m, in ComputeThisAdjustments()
1166 // We need to record the method because we cannot in ComputeThisAdjustments()
1167 // call findOriginalMethod to find the method that created the entry if in ComputeThisAdjustments()
1168 // the method in the entry requires adjustment. in ComputeThisAdjustments()
1170 // Do not set ThunkInfo::Method if Idx is already in VTableThunks. This in ComputeThisAdjustments()
1173 const CXXMethodDecl *Method = VTables.findOriginalMethodInMap(MD); in ComputeThisAdjustments() local
1174 VTableThunks[Idx].Method = Method; in ComputeThisAdjustments()
1175 VTableThunks[Idx].ThisType = Method->getThisType().getTypePtr(); in ComputeThisAdjustments()
1188 /// Clear the method info map. in ComputeThisAdjustments()
1215 if (MD->getParent() == MostDerivedClass) in ComputeThisAdjustments()
1252 if (!DerivedRD->isDerivedFrom(BaseRD, Paths)) in ComputeThisAdjustmentBaseOffset()
1263 // If we have a virtual base class, the non-virtual offset is relative in ComputeThisAdjustmentBaseOffset()
1273 // Otherwise, the non-virtual offset is relative to the derived class in ComputeThisAdjustmentBaseOffset()
1281 // invert the non-virtual offset here. in ComputeThisAdjustmentBaseOffset()
1282 Offset.NonVirtualOffset = -Offset.NonVirtualOffset; in ComputeThisAdjustmentBaseOffset()
1294 if (Overrider.Method->isPureVirtual()) in ComputeThisAdjustment()
1297 BaseSubobject OverriddenBaseSubobject(MD->getParent(), in ComputeThisAdjustment()
1300 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(), in ComputeThisAdjustment()
1333 // Set the non-virtual part of the adjustment. in ComputeThisAdjustment()
1358 /// OverridesIndirectMethodInBase - Return whether the given member function
1367 /// OverridesIndirectMethodInBase will return true if given C::f as the method
1372 if (Bases.count(MD->getParent())) in OverridesIndirectMethodInBases()
1375 for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) { in OverridesIndirectMethodInBases()
1399 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain) in IsOverriderUsed()
1448 /// FindNearestOverriddenMethod - Given a method, returns the overridden method
1449 /// from the nearest base. Returns null if no method was found.
1450 /// The Bases are expected to be sorted in a base-to-derived order.
1460 // We found our overridden method. in FindNearestOverriddenMethod()
1461 if (OverriddenMD->getParent() == PrimaryBase) in FindNearestOverriddenMethod()
1478 // There is an entry for any virtual function declared in a class, in AddMethods()
1526 for (const auto *MD : RD->methods()) { in AddMethods()
1529 MD = MD->getCanonicalDecl(); in AddMethods()
1535 // Check if this virtual member function overrides a method in a primary in AddMethods()
1544 // Replace the method info of the overridden method with our own in AddMethods()
1545 // method. in AddMethods()
1547 "Did not find the overridden method!"); in AddMethods()
1554 "Should not have method info for this method yet!"); in AddMethods()
1559 // If the overridden method exists in a virtual base class or a direct in AddMethods()
1570 Overrider.Method->getParent() == MostDerivedClass) { in AddMethods()
1576 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD); in AddMethods()
1581 AddThunk(Overrider.Method, in AddMethods()
1583 OverriddenMD->getThisType().getTypePtr())); in AddMethods()
1591 if (MD->isImplicit()) in AddMethods()
1602 if (A->isCopyAssignmentOperator() != B->isCopyAssignmentOperator()) in AddMethods()
1603 return A->isCopyAssignmentOperator(); in AddMethods()
1604 if (A->isMoveAssignmentOperator() != B->isMoveAssignmentOperator()) in AddMethods()
1605 return A->isMoveAssignmentOperator(); in AddMethods()
1608 assert(A->getOverloadedOperator() == OO_EqualEqual && in AddMethods()
1609 B->getOverloadedOperator() == OO_EqualEqual && in AddMethods()
1623 // Insert the method info for this method. in AddMethods()
1628 "Should not have method info for this method yet!"); in AddMethods()
1632 const CXXMethodDecl *OverriderMD = Overrider.Method; in AddMethods()
1643 if (!OverriderMD->isPureVirtual()) { in AddMethods()
1651 // If a return adjustment is required, record the method that created the in AddMethods()
1652 // vtable entry. We need to record the method because we cannot call in AddMethods()
1653 // findOriginalMethod to find the method that created the entry if the in AddMethods()
1654 // method in the entry requires adjustment. in AddMethods()
1656 VTableThunks[Components.size()].Method = MD; in AddMethods()
1657 VTableThunks[Components.size()].ThisType = MD->getThisType().getTypePtr(); in AddMethods()
1660 AddMethod(Overrider.Method, ReturnAdjustment); in AddMethods()
1680 // -fapple-kext adds an extra entry at end of vtbl. in LayoutVTable()
1689 assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); in LayoutPrimaryAndSecondaryVTables()
1714 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass; in LayoutPrimaryAndSecondaryVTables()
1737 = MI.VTableIndex - AddressPoint; in LayoutPrimaryAndSecondaryVTables()
1739 = MI.VTableIndex + 1 - AddressPoint; in LayoutPrimaryAndSecondaryVTables()
1741 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint; in LayoutPrimaryAndSecondaryVTables()
1754 unsigned(VTableIndices.size() - 1), in LayoutPrimaryAndSecondaryVTables()
1755 unsigned(AddressPoint - VTableIndex)})); in LayoutPrimaryAndSecondaryVTables()
1796 for (const auto &B : RD->bases()) { in LayoutSecondaryVTables()
1801 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in LayoutSecondaryVTables()
1804 if (!BaseDecl->isDynamicClass()) in LayoutSecondaryVTables()
1813 if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases()) in LayoutSecondaryVTables()
1874 for (const auto &B : RD->bases()) { in DeterminePrimaryVirtualBases()
1875 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in DeterminePrimaryVirtualBases()
1903 for (const auto &B : RD->bases()) { in LayoutVTablesForVirtualBases()
1904 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); in LayoutVTablesForVirtualBases()
1908 if (B.isVirtual() && BaseDecl->isDynamicClass() && in LayoutVTablesForVirtualBases()
1930 if (BaseDecl->getNumVBases()) in LayoutVTablesForVirtualBases()
1936 if (!Info.Method) in printThunkMethod()
1939 PredefinedIdentKind::PrettyFunctionNoVirtual, Info.Method); in printThunkMethod()
1940 Out << " method: " << Str; in printThunkMethod()
1943 /// dumpLayout - Dump the vtable layout.
1957 Out << " " << Str0 << " -> " << Str1 << "\n"; in dumpLayout()
1962 MostDerivedClass->printQualifiedName(Out); in dumpLayout()
1965 LayoutClass->printQualifiedName(Out); in dumpLayout()
1968 MostDerivedClass->printQualifiedName(Out); in dumpLayout()
2014 Component.getRTTIDecl()->printQualifiedName(Out); in dumpLayout()
2024 if (MD->isPureVirtual()) in dumpLayout()
2027 if (MD->isDeleted()) in dumpLayout()
2035 Out << Thunk.Return.NonVirtual << " non-virtual"; in dumpLayout()
2049 Out << Thunk.This.NonVirtual << " non-virtual"; in dumpLayout()
2071 DD->printQualifiedName(Out); in dumpLayout()
2077 if (DD->isPureVirtual()) in dumpLayout()
2085 Out << Thunk.This.NonVirtual << " non-virtual"; in dumpLayout()
2106 if (MD->isPureVirtual()) in dumpLayout()
2119 AddressPointsByIndex.find(NextIndex)->second; in dumpLayout()
2121 Out << " -- ("; in dumpLayout()
2122 Base.getBase()->printQualifiedName(Out); in dumpLayout()
2124 Out << ") vtable address --\n"; in dumpLayout()
2127 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset(); in dumpLayout()
2136 ClassNames.insert(RD->getQualifiedNameAsString()); in dumpLayout()
2140 Out << " -- (" << Name; in dumpLayout()
2141 Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n"; in dumpLayout()
2152 if (MostDerivedClass->getNumVBases()) { in dumpLayout()
2158 std::string ClassName = I.first->getQualifiedNameAsString(); in dumpLayout()
2164 MostDerivedClass->printQualifiedName(Out); in dumpLayout()
2167 Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n"; in dumpLayout()
2176 // We store the method names in a map to get a stable order. in dumpLayout()
2197 Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; in dumpLayout()
2207 Out << " non-virtual"; in dumpLayout()
2220 Out << Thunk.This.NonVirtual << " non-virtual"; in dumpLayout()
2239 for (const auto *MD : MostDerivedClass->methods()) { in dumpLayout()
2243 MD = MD->getCanonicalDecl(); in dumpLayout()
2263 MostDerivedClass->printQualifiedName(Out); in dumpLayout()
2285 const auto &addressPointLoc = it->second; in MakeAddressPointIndices()
2316 this->VTableIndices = OwningArrayRef<size_t>(VTableIndices); in VTableLayout()
2318 llvm::sort(this->VTableThunks, [](const VTableLayout::VTableThunkTy &LHS, in VTableLayout()
2329 return MD->isVirtual() && !MD->isImmediateFunction(); in hasVtableSlot()
2342 return I->second; in getMethodVTableIndex()
2344 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent(); in getMethodVTableIndex()
2350 return I->second; in getMethodVTableIndex()
2361 return I->second; in getVirtualBaseOffsetOffset()
2378 return I->second; in getVirtualBaseOffsetOffset()
2383 computeVTableRelatedInformation(MD->getParent()); in findOriginalMethod()
2393 // Traverse the chain of virtual methods until we find the method that added in findOriginalMethodInMap()
2394 // the v-table slot. in findOriginalMethodInMap()
2398 // MD doesn't exist in OriginalMethodMap, so it must be the method we are in findOriginalMethodInMap()
2403 // Set MD to the overridden method. in findOriginalMethodInMap()
2404 MD = I->second; in findOriginalMethodInMap()
2422 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD]; in computeVTableRelatedInformation() local
2425 if (Entry) in computeVTableRelatedInformation()
2430 Entry = CreateVTableLayout(Builder); in computeVTableRelatedInformation()
2441 if (!RD->getNumVBases()) in computeVTableRelatedInformation()
2445 RD->vbases_begin()->getType()->getAsCXXRecordDecl(); in computeVTableRelatedInformation()
2480 // 3. Virtual method definitions expect their 'this' parameter to point to the
2481 // first vfptr whose table provides a compatible overridden method. In many
2482 // cases, this permits the original vf-table entry to directly call
2483 // the method instead of passing through a thunk.
2486 // A compatible overridden method is one which does not have a non-trivial
2487 // covariant-return adjustment.
2489 // The first vfptr is the one with the lowest offset in the complete-object
2490 // layout of the defining class, and the method definition will subtract
2495 // object), the vf-table may require a this-adjustment thunk.
2498 // this-adjustment. Together with #3, this keeps vf-tables smaller and
2499 // eliminates the need for this-adjustment thunks in many cases, at the cost
2504 // a) a user-defined ctor/dtor
2506 // b) a method overriding a method in a virtual base.
2509 // you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
2520 /// VTables - Global vtable information.
2523 /// Context - The ASTContext which we will use for layout information.
2526 /// MostDerivedClass - The most derived class for which we're building this
2534 /// FinalOverriders - The final overriders of the most derived class.
2537 /// Components - The components of the vftable being built.
2545 /// MethodInfo - Contains information about a method in a vtable.
2548 /// VBTableIndex - The nonzero index in the vbtable that
2549 /// this method's base has, or zero.
2552 /// VFTableIndex - The index in the vftable that this method has.
2555 /// Shadowed - Indicates if this vftable slot is shadowed by
2556 /// a slot for a covariant-return override. If so, it shouldn't be printed
2560 /// UsesExtraSlot - Indicates if this vftable slot was created because
2576 /// MethodInfoMap - The information for all methods in the vftable we're
2582 /// VTableThunks - The thunks by vftable index in the vftable currently being
2589 /// Thunks - A map that contains all the thunks needed for all methods in the
2593 /// AddThunk - Add a thunk for the given method.
2604 /// ComputeThisOffset - Returns the 'this' argument offset for the given
2605 /// method, relative to the beginning of the MostDerivedClass.
2611 /// AddMethod - Add a single virtual member function to the vftable
2627 /// AddMethods - Add the methods of this base subobject and the relevant
2649 assert(MD == MD->getCanonicalDecl()); in LayoutVFTable()
2653 if (MD->getParent() != MostDerivedClass || MI.Shadowed) in LayoutVFTable()
2669 Context(MostDerivedClass->getASTContext()), in VFTableBuilder()
2738 // a->f();
2751 // a->f();
2762 // passed as "this" to that code. However, "a" points at B-8, so the respective
2763 // vftable entry should hold a thunk that adds 12 to the "this" argument before
2767 // for the given method, relative to the beginning of the MostDerivedClass.
2773 // Find the set of least derived bases that define the given method. in ComputeThisOffset()
2777 if (OverriddenMD->size_overridden_methods() == 0) in ComputeThisOffset()
2778 Bases.insert(OverriddenMD->getParent()); in ComputeThisOffset()
2779 // Don't recurse on this method if we've already collected it. in ComputeThisOffset()
2782 visitAllOverriddenMethods(Overrider.Method, in ComputeThisOffset()
2787 // in the base that defines the method. in ComputeThisOffset()
2792 Overrider.Method->getParent()->lookupInBases( in ComputeThisOffset()
2794 return Bases.count(Specifier->getType()->getAsCXXRecordDecl()); in ComputeThisOffset()
2799 // This implies that an offset of a non-virtual base will dominate an offset in ComputeThisOffset()
2801 // in the derived classes that inherit this method. in ComputeThisOffset()
2806 Context.getASTRecordLayout(Overrider.Method->getParent()); in ComputeThisOffset()
2815 QualType CurTy = Element.Base->getType(); in ComputeThisOffset()
2817 *CurRD = CurTy->getAsCXXRecordDecl(); in ComputeThisOffset()
2820 if (Element.Base->isVirtual()) { in ComputeThisOffset()
2825 // derived class and it overrides a method of the B's own vbase A, in ComputeThisOffset()
2829 // this-adjusting thunk in the vftable if A and B are laid out in ComputeThisOffset()
2838 if (isa<CXXDestructorDecl>(Overrider.Method)) { in ComputeThisOffset()
2840 // If a "Base" class has at least one non-virtual base with a virtual in ComputeThisOffset()
2857 assert(!First && "Method not found in the given subobject?"); in ComputeThisOffset()
2864 // a non-most-derived class construction or destruction.
2871 // void foo(A *a) { a->f(); } // Knows nothing about siblings of A.
2903 // - initializes all the vbptrs, then
2904 // - calls the A subobject constructor
2906 // - calls the B subobject constructor
2909 // - initializes A's vfptr with an address of C vftable and zeroes out the
2930 // yet the pointer foo() passes along is B-4 (i.e. C+8).
2933 // from the "this" argument (-12) before making a tailcall to B::f().
2954 // passes along A, which is C-8. The A vtordisp holds
2955 // "D.vbptr[index_of_A] - offset_of_A_in_D"
2970 if (!VBaseMapEntry->second.hasVtorDisp() || in CalculateVtordispAdjustment()
2976 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset; in CalculateVtordispAdjustment()
2978 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4; in CalculateVtordispAdjustment()
2981 // in either the most derived class or its non-virtual base. in CalculateVtordispAdjustment()
2982 if (Overrider.Method->getParent() == MostDerivedClass || in CalculateVtordispAdjustment()
2989 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset - in CalculateVtordispAdjustment()
2995 TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity(); in CalculateVtordispAdjustment()
3004 // (including overrides, non-virtual methods and any other named decl that in GroupNewVirtualOverloads()
3011 for (const auto *D : RD->decls()) { in GroupNewVirtualOverloads()
3018 std::make_pair(ND->getDeclName(), Groups.size())); in GroupNewVirtualOverloads()
3023 Groups[J->second].push_back(MD->getCanonicalDecl()); in GroupNewVirtualOverloads()
3031 for (const auto &B : RD->bases()) { in isDirectVBase()
3032 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base) in isDirectVBase()
3042 if (!RD->isPolymorphic()) in AddMethods()
3081 // - replacing overridden methods in their existing slots, as long as they in AddMethods()
3083 // - adding new slots for methods of the current base not present in any in AddMethods()
3084 // sub-bases; in AddMethods()
3085 // - adding new slots for methods that require Return adjustment. in AddMethods()
3086 // We keep track of the methods visited in the sub-bases in MethodInfoMap. in AddMethods()
3090 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method; in AddMethods()
3098 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity(); in AddMethods()
3113 // If the overridden method went to a different vftable, skip it. in AddMethods()
3117 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second; in AddMethods()
3124 // Once a chain of method overrides adds a return adjusting vftable slot, in AddMethods()
3125 // all subsequent overrides will also use an extra method slot. in AddMethods()
3131 // No return adjustment needed - just replace the overridden method info in AddMethods()
3137 "Should not have method info for this method yet!"); in AddMethods()
3143 // the overrider. Mark the overridden method as shadowed by the new slot. in AddMethods()
3146 // Force a special name mangling for a return-adjusting thunk in AddMethods()
3147 // unless the method is the final overrider without this adjustment. in AddMethods()
3151 MD->size_overridden_methods()) { in AddMethods()
3153 // e.g. each method that wasn't seen in any of the visited sub-bases in AddMethods()
3154 // but overrides multiple methods of other sub-bases. in AddMethods()
3158 // If we got here, MD is a method not seen in any of the sub-bases or in AddMethods()
3159 // it requires return adjustment. Insert the method info for this method. in AddMethods()
3161 HasRTTIComponent ? Components.size() - 1 : Components.size(), in AddMethods()
3165 "Should not have method info for this method yet!"); in AddMethods()
3172 if (!FinalOverriderMD->isPureVirtual()) { in AddMethods()
3190 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr(); in AddMethods()
3200 Elem->printQualifiedName(Out); in PrintBasePath()
3210 if (!R.isEmpty() || TI.Method) { in dumpMicrosoftThunkAdjustment()
3214 << TI.Method->getReturnType().getCanonicalType() << "'): "; in dumpMicrosoftThunkAdjustment()
3219 Out << R.NonVirtual << " non-virtual]"; in dumpMicrosoftThunkAdjustment()
3239 Out << T.NonVirtual << " non-virtual]"; in dumpMicrosoftThunkAdjustment()
3247 MostDerivedClass->printQualifiedName(Out); in dumpLayout()
3249 << (Components.size() == 1 ? " entry" : " entries") << ").\n"; in dumpLayout()
3259 Component.getRTTIDecl()->printQualifiedName(Out); in dumpLayout()
3271 if (MD->isPureVirtual()) in dumpLayout()
3274 if (MD->isDeleted()) in dumpLayout()
3287 DD->printQualifiedName(Out); in dumpLayout()
3290 if (DD->isPureVirtual()) in dumpLayout()
3308 Diags.Report(MostDerivedClass->getLocation(), DiagID) in dumpLayout()
3318 // We store the method names in a map to get a stable order. in dumpLayout()
3342 Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; in dumpLayout()
3370 /// Produces MSVC-compatible vbtable data. The symbols produced by this
3404 for (const auto &B : RD->bases()) { in computeVTablePaths()
3405 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); in computeVTablePaths()
3409 if (!Base->isDynamicClass()) in computeVTablePaths()
3418 if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases)) in computeVTablePaths()
3426 if (P->MangledPath.empty() || P->MangledPath.back() != Base) in computeVTablePaths()
3427 P->NextBaseToMangle = Base; in computeVTablePaths()
3431 // base, or the first non-virtual base that has a vbtable. in computeVTablePaths()
3432 if (P->ObjectWithVPtr == Base && in computeVTablePaths()
3435 P->ObjectWithVPtr = RD; in computeVTablePaths()
3438 // adjustment is captured by an optional vbase and a non-virtual offset. in computeVTablePaths()
3440 P->ContainingVBases.push_back(Base); in computeVTablePaths()
3441 else if (P->ContainingVBases.empty()) in computeVTablePaths()
3442 P->NonVirtualOffset += Layout.getBaseClassOffset(Base); in computeVTablePaths()
3445 P->FullOffsetInMDC = P->NonVirtualOffset; in computeVTablePaths()
3446 if (const CXXRecordDecl *VB = P->getVBaseWithVPtr()) in computeVTablePaths()
3447 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB); in computeVTablePaths()
3457 for (const auto &VB : Base->vbases()) in computeVTablePaths()
3458 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl()); in computeVTablePaths()
3500 if (I - BucketStart > 1) { in rebucketPaths()
3531 for (const CXXBaseSpecifier &BS : RD->bases()) { in findPathsToSubobject()
3532 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl(); in findPathsToSubobject()
3564 CharUnits Offset = CharUnits::fromQuantity(-1); in getOffsetOfFullPath()
3567 // The first entry in the path is always the most derived record, skip it. in getOffsetOfFullPath()
3569 assert(Offset.getQuantity() == -1); in getOffsetOfFullPath()
3573 assert(Offset.getQuantity() != -1); in getOffsetOfFullPath()
3578 RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) { in getOffsetOfFullPath()
3579 return BS.getType()->getAsCXXRecordDecl() == Base; in getOffsetOfFullPath()
3581 Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base) in getOffsetOfFullPath()
3607 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase(); in selectBestPath()
3613 for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) { in selectBestPath()
3617 Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset); in selectBestPath()
3618 const CXXMethodDecl *OverridingMethod = OI.Method; in selectBestPath()
3626 const CXXRecordDecl *OverridingParent = OverridingMethod->getParent(); in selectBestPath()
3648 Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component) in selectBestPath()
3650 Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk) in selectBestPath()
3652 Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk) in selectBestPath()
3670 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath, in computeFullPathsForVFTables()
3674 Info->PathToIntroducingObject.clear(); in computeFullPathsForVFTables()
3678 Info->PathToIntroducingObject.push_back(BSO.getBase()); in computeFullPathsForVFTables()
3697 assert(RD->isDynamicClass()); in computeVTableRelatedInformation()
3716 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC); in computeVTableRelatedInformation()
3730 MethodVFTableLocation &OldLoc = Insert.first->second; in computeVTableRelatedInformation()
3772 RD->printQualifiedName(Out); in dumpMethodLocations()
3774 << (IndicesMap.size() == 1 ? " entry" : " entries") << ").\n"; in dumpMethodLocations()
3776 CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1); in dumpMethodLocations()
3784 Out << " -- accessible via "; in dumpMethodLocations()
3787 Out << "vfptr at offset " << VFPtrOffset.getQuantity() << " --\n"; in dumpMethodLocations()
3809 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD]; in computeVBTableRelatedInformation() local
3810 if (Entry) in computeVBTableRelatedInformation()
3811 return *Entry; in computeVBTableRelatedInformation()
3812 Entry = std::make_unique<VirtualBaseInfo>(); in computeVBTableRelatedInformation()
3813 VBI = Entry.get(); in computeVBTableRelatedInformation()
3816 computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths); in computeVBTableRelatedInformation()
3818 // First, see if the Derived class shared the vbptr with a non-virtual base. in computeVBTableRelatedInformation()
3821 // If the Derived class shares the vbptr with a non-virtual base, the shared in computeVBTableRelatedInformation()
3825 VBI->VBTableIndices.insert(BaseInfo.VBTableIndices.begin(), in computeVBTableRelatedInformation()
3830 // Skip the self entry and vbases visited in the non-virtual base, if any. in computeVBTableRelatedInformation()
3831 unsigned VBTableIndex = 1 + VBI->VBTableIndices.size(); in computeVBTableRelatedInformation()
3832 for (const auto &VB : RD->vbases()) { in computeVBTableRelatedInformation()
3833 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl(); in computeVBTableRelatedInformation()
3834 if (!VBI->VBTableIndices.count(CurVBase)) in computeVBTableRelatedInformation()
3835 VBI->VBTableIndices[CurVBase] = VBTableIndex++; in computeVBTableRelatedInformation()
3845 return VBInfo.VBTableIndices.find(VBase)->second; in getVBTableIndex()
3874 "Only use this method for virtual methods or dtors"); in getMethodVFTableLocation()
3882 return I->second; in getMethodVFTableLocation()
3884 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent(); in getMethodVFTableLocation()
3890 return I->second; in getMethodVFTableLocation()