diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h index 53bb785c49d26a120827b298e35aac8e105452ff..06113954fc48aed263542306a811a13585efe2ed 100644 --- a/clang/include/clang/AST/ASTConsumer.h +++ b/clang/include/clang/AST/ASTConsumer.h @@ -16,6 +16,7 @@ namespace clang { class ASTContext; + class CXXRecordDecl; class DeclGroupRef; class TagDecl; class HandleTagDeclDefinition; @@ -68,6 +69,17 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} + /// \brief Callback involved at the end of a translation unit to + /// notify the consumer that a vtable for the given C++ class is + /// required. + /// + /// \param RD The class whose vtable was used. + /// + /// \param DefinitionRequired Whether a definition of this vtable is + /// required in this translation unit; otherwise, it is only needed if + /// it was actually used. + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index df0f641a50f2e6f4a45c876a1410056cfdb8febc..368e2483c862ff17404086592ad8d5d715a924f1 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -2788,7 +2788,13 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { // Check if we've computed this information before. if (LayoutData) return; - + + // We may need to generate a definition for this vtable. + if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) && + RD->getTemplateSpecializationKind() + != TSK_ExplicitInstantiationDeclaration) + CGM.DeferredVTables.push_back(RD); + VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); // Add the VTable layout. @@ -3119,49 +3125,3 @@ CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, DC->getParent()->isTranslationUnit()) CGM.EmitFundamentalRTTIDescriptors(); } - -void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) { - const CXXMethodDecl *MD = cast(GD.getDecl()); - const CXXRecordDecl *RD = MD->getParent(); - - // If the class doesn't have a vtable we don't need to emit one. - if (!RD->isDynamicClass()) - return; - - // Check if we need to emit thunks for this function. - if (MD->isVirtual()) - EmitThunks(GD); - - // Get the key function. - const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD); - - TemplateSpecializationKind RDKind = RD->getTemplateSpecializationKind(); - TemplateSpecializationKind MDKind = MD->getTemplateSpecializationKind(); - - if (KeyFunction) { - // We don't have the right key function. - if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) - return; - } else { - // If we have no key function and this is a explicit instantiation - // declaration, we will produce a vtable at the explicit instantiation. We - // don't need one here. - if (RDKind == clang::TSK_ExplicitInstantiationDeclaration) - return; - - // If this is an explicit instantiation of a method, we don't need a vtable. - // Since we have no key function, we will emit the vtable when we see - // a use, and just defining a function is not an use. - if (RDKind == TSK_ImplicitInstantiation && - MDKind == TSK_ExplicitInstantiationDefinition) - return; - } - - if (VTables.count(RD)) - return; - - if (RDKind == TSK_ImplicitInstantiation) - CGM.DeferredVTables.push_back(RD); - else - GenerateClassData(CGM.getVTableLinkage(RD), RD); -} diff --git a/clang/lib/CodeGen/CGVTables.h b/clang/lib/CodeGen/CGVTables.h index 6c18ca83f0919986c7d5bf15c8245af372bcf531..e55377f2fa2fe32acc602f8ae87b9f14940c5d4f 100644 --- a/clang/lib/CodeGen/CGVTables.h +++ b/clang/lib/CodeGen/CGVTables.h @@ -272,9 +272,6 @@ class CodeGenVTables { /// EmitThunk - Emit a single thunk. void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk); - /// EmitThunks - Emit the associated thunks for the given global decl. - void EmitThunks(GlobalDecl GD); - /// ComputeVTableRelatedInformation - Compute and store all vtable related /// information (vtable layout, vbase offset offsets, thunks etc) for the /// given record decl. @@ -349,11 +346,10 @@ public: VTableAddressPointsMapTy& AddressPoints); llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD); - - // EmitVTableRelatedData - Will emit any thunks that the global decl might - // have, as well as the vtable itself if the global decl is the key function. - void EmitVTableRelatedData(GlobalDecl GD); + /// EmitThunks - Emit the associated thunks for the given global decl. + void EmitThunks(GlobalDecl GD); + /// GenerateClassData - Generate all the class data required to be generated /// upon definition of a KeyFunction. This includes the vtable, the /// rtti data structure and the VTT. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 6cbc3f67c2d550c6f730000d697a83a607fe7076..6dd16e73b49903a5156ab97eb83b22cd6898c8a6 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -727,8 +727,9 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { Context.getSourceManager(), "Generating code for declaration"); - if (isa(D)) - getVTables().EmitVTableRelatedData(GD); + if (const CXXMethodDecl *Method = dyn_cast(D)) + if (Method->isVirtual()) + getVTables().EmitThunks(GD); if (const CXXConstructorDecl *CD = dyn_cast(D)) return EmitCXXConstructor(CD, GD.getCtorType()); @@ -984,6 +985,11 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { EmitGlobalVarDefinition(D); } +void CodeGenModule::EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired) { + if (DefinitionRequired) + getVTables().GenerateClassData(getVTableLinkage(Class), Class); +} + llvm::GlobalVariable::LinkageTypes CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 93d8ddf3e485029363c4c1a24090088cda342a63..0e4f4a932eef8988de293f43a509114caf675042 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -422,6 +422,8 @@ public: void EmitTentativeDefinition(const VarDecl *D); + void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired); + enum GVALinkage { GVA_Internal, GVA_C99Inline, diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 1e1edc1c482fd98e8c191de16f1b36c3aa794589..9905ca6f1dc81999f3b97151ce72997939b96513 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -89,6 +89,13 @@ namespace { Builder->EmitTentativeDefinition(D); } + + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { + if (Diags.hasErrorOccurred()) + return; + + Builder->EmitVTable(RD, DefinitionRequired); + } }; } diff --git a/clang/lib/Frontend/CodeGenAction.cpp b/clang/lib/Frontend/CodeGenAction.cpp index 79d7d5f4c2413ebfed68584b6404b871c6a4f2b2..86005f280ac7be1f4b90651f6ad50bb4ec5ba8e4 100644 --- a/clang/lib/Frontend/CodeGenAction.cpp +++ b/clang/lib/Frontend/CodeGenAction.cpp @@ -180,6 +180,10 @@ namespace { Gen->CompleteTentativeDefinition(D); } + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { + Gen->HandleVTable(RD, DefinitionRequired); + } + static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, unsigned LocCookie) { SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 91effa44b260f33d27727caaf48ef7c9db1c6590..569de3203aacdf59a2d182b9be96437a8371189b 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -164,6 +164,18 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, } } + // If this is a derived-to-base cast to a through a virtual base, we + // need a vtable. + if (Kind == CastExpr::CK_DerivedToBase && + BasePathInvolvesVirtualBase(BasePath)) { + QualType T = Expr->getType(); + if (const PointerType *Pointer = T->getAs()) + T = Pointer->getPointeeType(); + if (const RecordType *RecordTy = T->getAs()) + MarkVTableUsed(Expr->getLocStart(), + cast(RecordTy->getDecl())); + } + if (ImplicitCastExpr *ImpCast = dyn_cast(Expr)) { if (ImpCast->getCastKind() == Kind && BasePath.empty()) { ImpCast->setType(Ty); @@ -199,10 +211,10 @@ void Sema::ActOnEndOfTranslationUnit() { // template instantiations earlier. PerformPendingImplicitInstantiations(); - /// If ProcessPendingClassesWithUnmarkedVirtualMembers ends up marking - /// any virtual member functions it might lead to more pending template + /// If DefinedUsedVTables ends up marking any virtual member + /// functions it might lead to more pending template /// instantiations, which is why we need to loop here. - if (!ProcessPendingClassesWithUnmarkedVirtualMembers()) + if (!DefineUsedVTables()) break; } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 9d811a4dbe9c78d7303ad7ae1946037b28f937c5..4ef5ebe20a7cc6112940c56213b09e8b2727ac88 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2560,27 +2560,38 @@ public: void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc, CXXRecordDecl *Record); - /// ClassesWithUnmarkedVirtualMembers - Contains record decls whose virtual - /// members need to be marked as referenced at the end of the translation - /// unit. It will contain polymorphic classes that do not have a key - /// function or have a key function that has been defined. - llvm::SmallVector, 4> - ClassesWithUnmarkedVirtualMembers; - - /// MaybeMarkVirtualMembersReferenced - If the passed in method is the - /// key function of the record decl, will mark virtual member functions as - /// referenced. - void MaybeMarkVirtualMembersReferenced(SourceLocation Loc, CXXMethodDecl *MD); + /// \brief The list of classes whose vtables have been used within + /// this translation unit, and the source locations at which the + /// first use occurred. + llvm::SmallVector, 16> + VTableUses; + + /// \brief The set of classes whose vtables have been used within + /// this translation unit, and a bit that will be true if the vtable is + /// required to be emitted (otherwise, it should be emitted only if needed + /// by code generation). + llvm::DenseMap VTablesUsed; + + /// \brief A list of all of the dynamic classes in this translation + /// unit. + llvm::SmallVector DynamicClasses; + + /// \brief Note that the vtable for the given class was used at the + /// given location. + void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, + bool DefinitionRequired = false); /// MarkVirtualMembersReferenced - Will mark all virtual members of the given /// CXXRecordDecl referenced. void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD); - /// ProcessPendingClassesWithUnmarkedVirtualMembers - Will process classes - /// that might need to have their virtual members marked as referenced. - /// Returns false if no work was done. - bool ProcessPendingClassesWithUnmarkedVirtualMembers(); + /// \brief Define all of the vtables that have been used in this + /// translation unit and reference any virtual members used by those + /// vtables. + /// + /// \returns true if any work was done, false otherwise. + bool DefineUsedVTables(); void AddImplicitlyDeclaredMembersToClass(Scope *S, CXXRecordDecl *ClassDecl); @@ -2664,6 +2675,8 @@ public: void BuildBasePathArray(const CXXBasePaths &Paths, CXXBaseSpecifierArray &BasePath); + bool BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath); + bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXBaseSpecifierArray *BasePath = 0, diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 9f8b344562f80dd1c9e73961c6192bab2cb8bbe8..1dbdd06eeaba5dea71117dfe6cea16133488e80b 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -388,6 +388,12 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, return; Kind = CastExpr::CK_DerivedToBase; + + // If we are casting to or through a virtual base class, we need a + // vtable. + if (Self.BasePathInvolvesVirtualBase(BasePath)) + Self.MarkVTableUsed(OpRange.getBegin(), + cast(SrcRecord->getDecl())); return; } @@ -398,6 +404,8 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); } + Self.MarkVTableUsed(OpRange.getBegin(), + cast(SrcRecord->getDecl())); // Done. Everything else is run-time checks. Kind = CastExpr::CK_Dynamic; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b4f5d13d2a5e3032d82d03f0f2956331c94ff7dc..76334e9a1258afebaf58f16d48a4d885815a38a5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4575,12 +4575,14 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, WP.disableCheckFallThrough(); } - if (!FD->isInvalidDecl()) + if (!FD->isInvalidDecl()) { DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); - - if (CXXMethodDecl *Method = dyn_cast(FD)) - MaybeMarkVirtualMembersReferenced(Method->getLocation(), Method); - + + // If this is a constructor, we need a vtable. + if (CXXConstructorDecl *Constructor = dyn_cast(FD)) + MarkVTableUsed(FD->getLocation(), Constructor->getParent()); + } + assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); @@ -5447,37 +5449,6 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD, "Broken injected-class-name"); } -// Traverses the class and any nested classes, making a note of any -// dynamic classes that have no key function so that we can mark all of -// their virtual member functions as "used" at the end of the translation -// unit. This ensures that all functions needed by the vtable will get -// instantiated/synthesized. -static void -RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record, - SourceLocation Loc) { - // We don't look at dependent or undefined classes. - if (Record->isDependentContext() || !Record->isDefinition()) - return; - - if (Record->isDynamicClass()) { - const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record); - - if (!KeyFunction) - S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, - Loc)); - - if ((!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined())) - && Record->getLinkage() == ExternalLinkage) - S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record; - } - for (DeclContext::decl_iterator D = Record->decls_begin(), - DEnd = Record->decls_end(); - D != DEnd; ++D) { - if (CXXRecordDecl *Nested = dyn_cast(*D)) - RecordDynamicClassesWithNoKeyFunction(S, Nested, Loc); - } -} - void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, SourceLocation RBraceLoc) { AdjustDeclIfTemplate(TagD); @@ -5489,10 +5460,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, // Exit this scope of this tag's definition. PopDeclContext(); - - if (isa(Tag) && !Tag->getLexicalDeclContext()->isRecord()) - RecordDynamicClassesWithNoKeyFunction(*this, cast(Tag), - RBraceLoc); // Notify the consumer that we've defined a tag. Consumer.HandleTagDeclDefinition(Tag); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7f8d24515880e488c8f5be210600ac6ac1cb0467..558746b0fea827393b8f32bb99c0b8d99d427675 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -735,6 +735,18 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, BasePathArray.push_back(Path[I].Base); } +/// \brief Determine whether the given base path includes a virtual +/// base class. +bool Sema::BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath) { + for (CXXBaseSpecifierArray::iterator B = BasePath.begin(), + BEnd = BasePath.end(); + B != BEnd; ++B) + if ((*B)->isVirtual()) + return true; + + return false; +} + /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base /// conversion (where Derived and Base are class types) is /// well-formed, meaning that the conversion is unambiguous (and @@ -2466,6 +2478,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { } } } + + if (Record->isDynamicClass()) + DynamicClasses.push_back(Record); } void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, @@ -4154,7 +4169,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, Constructor->setInvalidDecl(); } else { Constructor->setUsed(); - MaybeMarkVirtualMembersReferenced(CurrentLocation, Constructor); + MarkVTableUsed(CurrentLocation, ClassDecl); } } @@ -4183,7 +4198,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, } Destructor->setUsed(); - MaybeMarkVirtualMembersReferenced(CurrentLocation, Destructor); + MarkVTableUsed(CurrentLocation, ClassDecl); } /// \brief Builds a statement that copies the given entity from \p From to @@ -4641,8 +4656,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); CopyAssignOperator->setBody(Body.takeAs()); - - MaybeMarkVirtualMembersReferenced(CurrentLocation, CopyAssignOperator); } void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, @@ -4670,7 +4683,6 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, MultiStmtArg(*this, 0, 0), /*isStmtExpr=*/false) .takeAs()); - MaybeMarkVirtualMembersReferenced(CurrentLocation, CopyConstructor); } CopyConstructor->setUsed(); @@ -6019,90 +6031,120 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { return Dcl; } -static bool needsVTable(CXXMethodDecl *MD, ASTContext &Context) { - // Ignore dependent types. - if (MD->isDependentContext()) - return false; - - // Ignore declarations that are not definitions. - if (!MD->isThisDeclarationADefinition()) - return false; - - CXXRecordDecl *RD = MD->getParent(); - - // Ignore classes without a vtable. - if (!RD->isDynamicClass()) - return false; - - switch (MD->getParent()->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - // Classes that aren't instantiations of templates don't need their - // virtual methods marked until we see the definition of the key - // function. - break; +void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, + bool DefinitionRequired) { + // Ignore any vtable uses in unevaluated operands or for classes that do + // not have a vtable. + if (!Class->isDynamicClass() || Class->isDependentContext() || + CurContext->isDependentContext() || + ExprEvalContexts.back().Context == Unevaluated) + return; - case TSK_ImplicitInstantiation: - // This is a constructor of a class template; mark all of the virtual - // members as referenced to ensure that they get instantiatied. - if (isa(MD) || isa(MD)) - return true; - break; + // Try to insert this class into the map. + Class = cast(Class->getCanonicalDecl()); + std::pair::iterator, bool> + Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired)); + if (!Pos.second) { + Pos.first->second = Pos.first->second || DefinitionRequired; + return; + } - case TSK_ExplicitInstantiationDeclaration: - return false; + // Local classes need to have their virtual members marked + // immediately. For all other classes, we mark their virtual members + // at the end of the translation unit. + if (Class->isLocalClass()) + MarkVirtualMembersReferenced(Loc, Class); + else + VTableUses.push_back(std::make_pair(Class, Loc)); +} - case TSK_ExplicitInstantiationDefinition: - // This is method of a explicit instantiation; mark all of the virtual - // members as referenced to ensure that they get instantiatied. - return true; +bool Sema::DefineUsedVTables() { + // If any dynamic classes have their key function defined within + // this translation unit, then those vtables are considered "used" and must + // be emitted. + for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) { + if (const CXXMethodDecl *KeyFunction + = Context.getKeyFunction(DynamicClasses[I])) { + const FunctionDecl *Definition = 0; + if (KeyFunction->getBody(Definition) && !Definition->isInlined() && + !Definition->isImplicit()) + MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true); + } } - // Consider only out-of-line definitions of member functions. When we see - // an inline definition, it's too early to compute the key function. - if (!MD->isOutOfLine()) + if (VTableUses.empty()) return false; + + // Note: The VTableUses vector could grow as a result of marking + // the members of a class as "used", so we check the size each + // time through the loop and prefer indices (with are stable) to + // iterators (which are not). + for (unsigned I = 0; I != VTableUses.size(); ++I) { + CXXRecordDecl *Class + = cast_or_null(VTableUses[I].first)->getDefinition(); + if (!Class) + continue; - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - - // If there is no key function, we will need a copy of the vtable. - if (!KeyFunction) - return true; - - // If this is the key function, we need to mark virtual members. - if (KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl()) - return true; - - return false; -} - -void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, - CXXMethodDecl *MD) { - CXXRecordDecl *RD = MD->getParent(); + SourceLocation Loc = VTableUses[I].second; + + // If this class has a key function, but that key function is + // defined in another translation unit, we don't need to emit the + // vtable even though we're using it. + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class); + if (KeyFunction && !KeyFunction->getBody()) { + switch (KeyFunction->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + // The key function is in another translation unit. + continue; - // We will need to mark all of the virtual members as referenced to build the - // vtable. - if (!needsVTable(MD, Context)) - return; + case TSK_ExplicitInstantiationDefinition: + case TSK_ImplicitInstantiation: + // We will be instantiating the key function. + break; + } + } else if (!KeyFunction) { + // If we have a class with no key function that is the subject + // of an explicit instantiation declaration, suppress the + // vtable; it will live with the explicit instantiation + // definition. + bool IsExplicitInstantiationDeclaration + = Class->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDeclaration; + for (TagDecl::redecl_iterator R = Class->redecls_begin(), + REnd = Class->redecls_end(); + R != REnd; ++R) { + TemplateSpecializationKind TSK + = cast(*R)->getTemplateSpecializationKind(); + if (TSK == TSK_ExplicitInstantiationDeclaration) + IsExplicitInstantiationDeclaration = true; + else if (TSK == TSK_ExplicitInstantiationDefinition) { + IsExplicitInstantiationDeclaration = false; + break; + } + } - TemplateSpecializationKind kind = RD->getTemplateSpecializationKind(); - if (kind == TSK_ImplicitInstantiation) - ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); - else - MarkVirtualMembersReferenced(Loc, RD); -} + if (IsExplicitInstantiationDeclaration) + continue; + } -bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() { - if (ClassesWithUnmarkedVirtualMembers.empty()) - return false; - - while (!ClassesWithUnmarkedVirtualMembers.empty()) { - CXXRecordDecl *RD = ClassesWithUnmarkedVirtualMembers.back().first; - SourceLocation Loc = ClassesWithUnmarkedVirtualMembers.back().second; - ClassesWithUnmarkedVirtualMembers.pop_back(); - MarkVirtualMembersReferenced(Loc, RD); + // Mark all of the virtual members of this class as referenced, so + // that we can build a vtable. Then, tell the AST consumer that a + // vtable for this class is required. + MarkVirtualMembersReferenced(Loc, Class); + CXXRecordDecl *Canonical = cast(Class->getCanonicalDecl()); + Consumer.HandleVTable(Class, VTablesUsed[Canonical]); + + // Optionally warn if we're emitting a weak vtable. + if (Class->getLinkage() == ExternalLinkage && + Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + if (!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined())) + Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; + } } - + VTableUses.clear(); + return true; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 73493b60662b15698de8bc5ab1ad684c0293a536..13f44b9a8a9df37f04cd5844d4bbd4fe7ef76b22 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7503,17 +7503,19 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); } - MaybeMarkVirtualMembersReferenced(Loc, Constructor); + MarkVTableUsed(Loc, Constructor->getParent()); } else if (CXXDestructorDecl *Destructor = dyn_cast(D)) { if (Destructor->isImplicit() && !Destructor->isUsed()) DefineImplicitDestructor(Loc, Destructor); - + if (Destructor->isVirtual()) + MarkVTableUsed(Loc, Destructor->getParent()); } else if (CXXMethodDecl *MethodDecl = dyn_cast(D)) { if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() && MethodDecl->getOverloadedOperator() == OO_Equal) { if (!MethodDecl->isUsed()) DefineImplicitCopyAssignment(Loc, MethodDecl); - } + } else if (MethodDecl->isVirtual()) + MarkVTableUsed(Loc, MethodDecl->getParent()); } if (FunctionDecl *Function = dyn_cast(D)) { // Implicit instantiation of function templates and member functions of diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 8b17f8483d83aa3de2b398dc880b471b5ea0f9e0..15c21008bed38a052ffe1de37689d5f5ab1b8e93 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -314,8 +314,12 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, // When typeid is applied to an expression other than an lvalue of a // polymorphic class type [...] [the] expression is an unevaluated // operand. [...] - if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) + if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) { isUnevaluatedOperand = false; + + // We require a vtable to query the type at run time. + MarkVTableUsed(TypeidLoc, RecordD); + } } // C++ [expr.typeid]p4: @@ -445,6 +449,12 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { if (Res.isInvalid()) return true; E = Res.takeAs(); + + // If we are throwing a polymorphic class type or pointer thereof, + // exception handling will make use of the vtable. + if (const RecordType *RecordTy = Ty->getAs()) + MarkVTableUsed(ThrowLoc, cast(RecordTy->getDecl())); + return false; } @@ -1802,17 +1812,24 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; } - case ICK_Derived_To_Base: + case ICK_Derived_To_Base: { + CXXBaseSpecifierArray BasePath; if (CheckDerivedToBaseConversion(From->getType(), ToType.getNonReferenceType(), From->getLocStart(), - From->getSourceRange(), 0, + From->getSourceRange(), + &BasePath, IgnoreBaseAccess)) return true; + ImpCastExprToType(From, ToType.getNonReferenceType(), - CastExpr::CK_DerivedToBase); + CastExpr::CK_DerivedToBase, + /*isLvalue=*/(From->getType()->isRecordType() && + From->isLvalue(Context) == Expr::LV_Valid), + BasePath); break; - + } + default: assert(false && "Improper second standard conversion"); break; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index fea7e6129f15127b9a467d8f2fbc37aaa9959c1f..851fb9e83530933ee2e3827bc971618919fd5582 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3540,6 +3540,15 @@ InitializationSequence::Perform(Sema &S, &BasePath, IgnoreBaseAccess)) return S.ExprError(); + if (S.BasePathInvolvesVirtualBase(BasePath)) { + QualType T = SourceType; + if (const PointerType *Pointer = T->getAs()) + T = Pointer->getPointeeType(); + if (const RecordType *RecordTy = T->getAs()) + S.MarkVTableUsed(CurInitExpr->getLocStart(), + cast(RecordTy->getDecl())); + } + CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type, CastExpr::CK_DerivedToBase, (Expr*)CurInit.release(), diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0f3f86dbfd4e414ed8534fc752d9e05504f9b086..9009b4d89773bfc54f8ec8e246d1f8671b12519f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4597,7 +4597,6 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { } // Explicit instantiation of a class template specialization -// FIXME: Implement extern template semantics Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, @@ -4760,7 +4759,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->getDefinition()); if (!Def) InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK); - + else if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(TemplateNameLoc, Specialization, true); + // Instantiate the members of this class template specialization. Def = cast_or_null( Specialization->getDefinition()); @@ -4895,6 +4896,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, InstantiateClassMembers(NameLoc, RecordDef, getTemplateInstantiationArgs(Record), TSK); + if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(NameLoc, RecordDef, true); + // FIXME: We don't have any representation for explicit instantiations of // member classes. Such a representation is not needed for compilation, but it // should be available for clients that want to see all of the declarations in diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 589b995653671febc328f153f6bbd5234ee1ed40..0e4dfcb14cb090cfe79c35315c0e0d0e8f8631fd 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1221,25 +1221,15 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // Exit the scope of this instantiation. SavedContext.pop(); - // If this is a polymorphic C++ class without a key function, we'll - // have to mark all of the virtual members to allow emission of a vtable - // in this translation unit. - if (Instantiation->isDynamicClass() && - !Context.getKeyFunction(Instantiation)) { - // Local classes need to have their methods instantiated immediately in - // order to have the correct instantiation scope. - if (Instantiation->isLocalClass()) { - MarkVirtualMembersReferenced(PointOfInstantiation, - Instantiation); - } else { - ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Instantiation, - PointOfInstantiation)); - } - } - - if (!Invalid) + if (!Invalid) { Consumer.HandleTagDeclDefinition(Instantiation); + // Always emit the vtable for an explicit instantiation definition + // of a polymorphic class template specialization. + if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(PointOfInstantiation, Instantiation, true); + } + return Invalid; } @@ -1263,6 +1253,12 @@ Sema::InstantiateClassTemplateSpecialization( // declaration (C++0x [temp.explicit]p10); go ahead and perform the // explicit instantiation. ClassTemplateSpec->setSpecializationKind(TSK); + + // If this is an explicit instantiation definition, mark the + // vtable as used. + if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true); + return false; } diff --git a/clang/test/CodeGenCXX/cxx-apple-kext.cpp b/clang/test/CodeGenCXX/cxx-apple-kext.cpp index 8d67b53657af428f85580ce07596f4cc71edc53c..4ba69069bedda7e04bd8773561c5c8150d09db58 100644 --- a/clang/test/CodeGenCXX/cxx-apple-kext.cpp +++ b/clang/test/CodeGenCXX/cxx-apple-kext.cpp @@ -3,9 +3,9 @@ // RUN: %clang -ccc-host-triple x86_64-apple-darwin10 %s -fapple-kext -flto -S -o - |\ // RUN: FileCheck --check-prefix=CHECK-KEXT %s -// CHECK-NO-KEXT: @_ZTI3foo = {{.*}} @_ZTVN10__cxxabiv117 // CHECK-NO-KEXT-NOT: _GLOBAL__D_a // CHECK-NO-KEXT: @is_hosted = global +// CHECK-NO-KEXT: @_ZTI3foo = {{.*}} @_ZTVN10__cxxabiv117 // CHECK-NO-KEXT: call i32 @__cxa_atexit({{.*}} @_ZN3fooD1Ev // CHECK-NO-KEXT: declare i32 @__cxa_atexit diff --git a/clang/test/CodeGenCXX/rtti-linkage.cpp b/clang/test/CodeGenCXX/rtti-linkage.cpp index b9eb5b4ad411313fd24094528512c62756a1c1db..d83048d89583459729021b1cfbc936ec987a3e5e 100644 --- a/clang/test/CodeGenCXX/rtti-linkage.cpp +++ b/clang/test/CodeGenCXX/rtti-linkage.cpp @@ -1,47 +1,49 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | sort | FileCheck %s #include -// CHECK: _ZTS1B = constant -// CHECK: _ZTS1A = weak_odr constant + + +// CHECK: _ZTIN12_GLOBAL__N_11DE to + + + // CHECK: _ZTI1A = weak_odr constant // CHECK: _ZTI1B = constant -// CHECK: _ZTSP1C = internal constant -// CHECK: _ZTS1C = internal constant // CHECK: _ZTI1C = internal constant -// CHECK: _ZTIP1C = internal constant -// CHECK: _ZTSPP1C = internal constant -// CHECK: _ZTIPP1C = internal constant -// CHECK: _ZTSM1Ci = internal constant -// CHECK: _ZTIM1Ci = internal constant -// CHECK: _ZTSPM1Ci = internal constant -// CHECK: _ZTIPM1Ci = internal constant -// CHECK: _ZTSM1CS_ = internal constant -// CHECK: _ZTIM1CS_ = internal constant -// CHECK: _ZTSM1CPS_ = internal constant -// CHECK: _ZTIM1CPS_ = internal constant -// CHECK: _ZTSM1A1C = internal constant +// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant +// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant +// CHECK: _ZTIFvvE = weak_odr // CHECK: _ZTIM1A1C = internal constant -// CHECK: _ZTSM1AP1C = internal constant // CHECK: _ZTIM1AP1C = internal constant - -// CHECK: _ZTS1F = weak_odr constant - -// CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant +// CHECK: _ZTIM1CPS_ = internal constant +// CHECK: _ZTIM1CS_ = internal constant +// CHECK: _ZTIM1Ci = internal constant // CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant +// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant +// CHECK: _ZTIP1C = internal constant +// CHECK: _ZTIPFvvE = weak_odr constant +// CHECK: _ZTIPM1Ci = internal constant // CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant +// CHECK: _ZTIPP1C = internal constant +// CHECK: _ZTS1A = weak_odr constant +// CHECK: _ZTS1B = constant +// CHECK: _ZTS1C = internal constant +// CHECK: _ZTS1F = weak_odr constant // CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant -// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant // CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant -// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant - -// CHECK: _ZTSPFvvE = weak_odr constant // CHECK: _ZTSFvvE = weak_odr constant -// CHECK: _ZTIFvvE = weak_odr -// CHECK: _ZTIPFvvE = weak_odr constant - +// CHECK: _ZTSM1A1C = internal constant +// CHECK: _ZTSM1AP1C = internal constant +// CHECK: _ZTSM1CPS_ = internal constant +// CHECK: _ZTSM1CS_ = internal constant +// CHECK: _ZTSM1Ci = internal constant +// CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant -// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant +// CHECK: _ZTSP1C = internal constant +// CHECK: _ZTSPFvvE = weak_odr constant +// CHECK: _ZTSPM1Ci = internal constant +// CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant +// CHECK: _ZTSPP1C = internal constant // A has no key function, so its RTTI data should be weak_odr. struct A { }; @@ -99,6 +101,5 @@ const std::type_info &t2() { (void)typeid(E); - // CHECK: _ZTIN12_GLOBAL__N_11DE to return typeid(getD()); } diff --git a/clang/test/CodeGenCXX/thunks.cpp b/clang/test/CodeGenCXX/thunks.cpp index b91ba3239b1e12c649440c47b99fe30dfc42e92b..7d2edaa7457b4b7d3fd99aeac6be9940a143e21f 100644 --- a/clang/test/CodeGenCXX/thunks.cpp +++ b/clang/test/CodeGenCXX/thunks.cpp @@ -88,6 +88,7 @@ void C::f() { } // This is from Test5: // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv +// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv( // Check that the thunk gets internal linkage. namespace { @@ -106,7 +107,6 @@ struct C : A, B { virtual void f(); }; -// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv( void C::f() { } } diff --git a/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp b/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp index 7de9dd2a608595de2487d95ac51f121c1114f477..22c49a089d0d2ba33c5159c7c7e4b7686fab73d4 100644 --- a/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -49,3 +49,4 @@ int main() { // CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev // CHECK-NOT: call // CHECK: } + diff --git a/clang/test/CodeGenCXX/virtual-functions-incomplete-types.cpp b/clang/test/CodeGenCXX/virtual-functions-incomplete-types.cpp index 50e04357b390304541eb10d26d71a40e5698737c..991c2bc7220f80758f268dfff4d5a8c40bba95c3 100644 --- a/clang/test/CodeGenCXX/virtual-functions-incomplete-types.cpp +++ b/clang/test/CodeGenCXX/virtual-functions-incomplete-types.cpp @@ -9,6 +9,7 @@ struct B { void B::f() { } +// CHECK: define i64 @_ZN1D1gEv(%struct.B* %this) // CHECK: declare void @_ZN1B1gEv() struct C; @@ -24,7 +25,6 @@ struct C { int a; }; -// CHECK: define i64 @_ZN1D1gEv(%struct.B* %this) C D::g() { return C(); } diff --git a/clang/test/CodeGenCXX/vtable-layout.cpp b/clang/test/CodeGenCXX/vtable-layout.cpp index f2f5179d4a19f539fb5c330e0ea7cc274544bbef..60b46fec39b38d58eaf6b35a2a53729b5a7ffaba 100644 --- a/clang/test/CodeGenCXX/vtable-layout.cpp +++ b/clang/test/CodeGenCXX/vtable-layout.cpp @@ -1,4 +1,46 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts > %t 2>&1 +// RUN: FileCheck --check-prefix=CHECK-1 %s < %t +// RUN: FileCheck --check-prefix=CHECK-2 %s < %t +// RUN: FileCheck --check-prefix=CHECK-3 %s < %t +// RUN: FileCheck --check-prefix=CHECK-4 %s < %t +// RUN: FileCheck --check-prefix=CHECK-5 %s < %t +// RUN: FileCheck --check-prefix=CHECK-6 %s < %t +// RUN: FileCheck --check-prefix=CHECK-7 %s < %t +// RUN: FileCheck --check-prefix=CHECK-8 %s < %t +// RUN: FileCheck --check-prefix=CHECK-9 %s < %t +// RUN: FileCheck --check-prefix=CHECK-10 %s < %t +// RUN: FileCheck --check-prefix=CHECK-11 %s < %t +// RUN: FileCheck --check-prefix=CHECK-12 %s < %t +// RUN: FileCheck --check-prefix=CHECK-13 %s < %t +// RUN: FileCheck --check-prefix=CHECK-14 %s < %t +// RUN: FileCheck --check-prefix=CHECK-15 %s < %t +// RUN: FileCheck --check-prefix=CHECK-16 %s < %t +// RUN: FileCheck --check-prefix=CHECK-17 %s < %t +// RUN: FileCheck --check-prefix=CHECK-18 %s < %t +// RUN: FileCheck --check-prefix=CHECK-19 %s < %t +// RUN: FileCheck --check-prefix=CHECK-20 %s < %t +// RUN: FileCheck --check-prefix=CHECK-21 %s < %t +// RUN: FileCheck --check-prefix=CHECK-22 %s < %t +// RUN: FileCheck --check-prefix=CHECK-23 %s < %t +// RUN: FileCheck --check-prefix=CHECK-24 %s < %t +// RUN: FileCheck --check-prefix=CHECK-25 %s < %t +// RUN: FileCheck --check-prefix=CHECK-26 %s < %t +// RUN: FileCheck --check-prefix=CHECK-27 %s < %t +// RUN: FileCheck --check-prefix=CHECK-28 %s < %t +// RUN: FileCheck --check-prefix=CHECK-29 %s < %t +// RUN: FileCheck --check-prefix=CHECK-30 %s < %t +// RUN: FileCheck --check-prefix=CHECK-31 %s < %t +// RUN: FileCheck --check-prefix=CHECK-32 %s < %t +// RUN: FileCheck --check-prefix=CHECK-33 %s < %t +// RUN: FileCheck --check-prefix=CHECK-34 %s < %t +// RUN: FileCheck --check-prefix=CHECK-35 %s < %t +// RUN: FileCheck --check-prefix=CHECK-36 %s < %t +// RUN: FileCheck --check-prefix=CHECK-37 %s < %t +// RUN: FileCheck --check-prefix=CHECK-38 %s < %t +// RUN: FileCheck --check-prefix=CHECK-39 %s < %t +// RUN: FileCheck --check-prefix=CHECK-40 %s < %t +// RUN: FileCheck --check-prefix=CHECK-41 %s < %t +// RUN: FileCheck --check-prefix=CHECK-42 %s < %t // For now, just verify this doesn't crash. namespace test0 { @@ -11,11 +53,11 @@ namespace test0 { } namespace Test1 { -// CHECK: Vtable for 'Test1::A' (3 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test1::A RTTI -// CHECK-NEXT: -- (Test1::A, 0) vtable address -- -// CHECK-NEXT: 2 | void Test1::A::f() +// CHECK-1: Vtable for 'Test1::A' (3 entries). +// CHECK-1-NEXT: 0 | offset_to_top (0) +// CHECK-1-NEXT: 1 | Test1::A RTTI +// CHECK-1-NEXT: -- (Test1::A, 0) vtable address -- +// CHECK-1-NEXT: 2 | void Test1::A::f() struct A { virtual void f(); }; @@ -26,17 +68,17 @@ void A::f() { } namespace Test2 { // This is a smoke test of the vtable dumper. -// CHECK: Vtable for 'Test2::A' (9 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test2::A RTTI -// CHECK-NEXT: -- (Test2::A, 0) vtable address -- -// CHECK-NEXT: 2 | void Test2::A::f() -// CHECK-NEXT: 3 | void Test2::A::f() const -// CHECK-NEXT: 4 | Test2::A *Test2::A::g(int) -// CHECK-NEXT: 5 | Test2::A::~A() [complete] -// CHECK-NEXT: 6 | Test2::A::~A() [deleting] -// CHECK-NEXT: 7 | void Test2::A::h() -// CHECK-NEXT: 8 | Test2::A &Test2::A::operator=(Test2::A const &) +// CHECK-2: Vtable for 'Test2::A' (9 entries). +// CHECK-2-NEXT: 0 | offset_to_top (0) +// CHECK-2-NEXT: 1 | Test2::A RTTI +// CHECK-2-NEXT: -- (Test2::A, 0) vtable address -- +// CHECK-2-NEXT: 2 | void Test2::A::f() +// CHECK-2-NEXT: 3 | void Test2::A::f() const +// CHECK-2-NEXT: 4 | Test2::A *Test2::A::g(int) +// CHECK-2-NEXT: 5 | Test2::A::~A() [complete] +// CHECK-2-NEXT: 6 | Test2::A::~A() [deleting] +// CHECK-2-NEXT: 7 | void Test2::A::h() +// CHECK-2-NEXT: 8 | Test2::A &Test2::A::operator=(Test2::A const &) struct A { virtual void f(); virtual void f() const; @@ -50,14 +92,14 @@ void A::f() { } // Another simple vtable dumper test. -// CHECK: Vtable for 'Test2::B' (6 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test2::B RTTI -// CHECK-NEXT: -- (Test2::B, 0) vtable address -- -// CHECK-NEXT: 2 | void Test2::B::f() -// CHECK-NEXT: 3 | void Test2::B::g() [pure] -// CHECK-NEXT: 4 | Test2::B::~B() [complete] [pure] -// CHECK-NEXT: 5 | Test2::B::~B() [deleting] [pure] +// CHECK-3: Vtable for 'Test2::B' (6 entries). +// CHECK-3-NEXT: 0 | offset_to_top (0) +// CHECK-3-NEXT: 1 | Test2::B RTTI +// CHECK-3-NEXT: -- (Test2::B, 0) vtable address -- +// CHECK-3-NEXT: 2 | void Test2::B::f() +// CHECK-3-NEXT: 3 | void Test2::B::g() [pure] +// CHECK-3-NEXT: 4 | Test2::B::~B() [complete] [pure] +// CHECK-3-NEXT: 5 | Test2::B::~B() [deleting] [pure] struct B { virtual void f(); virtual void g() = 0; @@ -73,52 +115,52 @@ namespace Test3 { // then the function should not have an entry in the derived class (unless the return // value requires adjusting). -// CHECK: Vtable for 'Test3::A' (3 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test3::A RTTI -// CHECK-NEXT: -- (Test3::A, 0) vtable address -- -// CHECK-NEXT: 2 | void Test3::A::f() +// CHECK-4: Vtable for 'Test3::A' (3 entries). +// CHECK-4-NEXT: 0 | offset_to_top (0) +// CHECK-4-NEXT: 1 | Test3::A RTTI +// CHECK-4-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-4-NEXT: 2 | void Test3::A::f() struct A { virtual void f(); }; void A::f() { } -// CHECK: Vtable for 'Test3::B' (4 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test3::B RTTI -// CHECK-NEXT: -- (Test3::A, 0) vtable address -- -// CHECK-NEXT: -- (Test3::B, 0) vtable address -- -// CHECK-NEXT: 2 | void Test3::B::f() -// CHECK-NEXT: 3 | void Test3::B::g() +// CHECK-5: Vtable for 'Test3::B' (4 entries). +// CHECK-5-NEXT: 0 | offset_to_top (0) +// CHECK-5-NEXT: 1 | Test3::B RTTI +// CHECK-5-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-5-NEXT: -- (Test3::B, 0) vtable address -- +// CHECK-5-NEXT: 2 | void Test3::B::f() +// CHECK-5-NEXT: 3 | void Test3::B::g() struct B : A { virtual void f(); virtual void g(); }; void B::f() { } -// CHECK: Vtable for 'Test3::C' (5 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test3::C RTTI -// CHECK-NEXT: -- (Test3::A, 0) vtable address -- -// CHECK-NEXT: -- (Test3::C, 0) vtable address -- -// CHECK-NEXT: 2 | void Test3::A::f() -// CHECK-NEXT: 3 | void Test3::C::g() -// CHECK-NEXT: 4 | void Test3::C::h() +// CHECK-6: Vtable for 'Test3::C' (5 entries). +// CHECK-6-NEXT: 0 | offset_to_top (0) +// CHECK-6-NEXT: 1 | Test3::C RTTI +// CHECK-6-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-6-NEXT: -- (Test3::C, 0) vtable address -- +// CHECK-6-NEXT: 2 | void Test3::A::f() +// CHECK-6-NEXT: 3 | void Test3::C::g() +// CHECK-6-NEXT: 4 | void Test3::C::h() struct C : A { virtual void g(); virtual void h(); }; void C::g() { } -// CHECK: Vtable for 'Test3::D' (5 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test3::D RTTI -// CHECK-NEXT: -- (Test3::A, 0) vtable address -- -// CHECK-NEXT: -- (Test3::B, 0) vtable address -- -// CHECK-NEXT: -- (Test3::D, 0) vtable address -- -// CHECK-NEXT: 2 | void Test3::D::f() -// CHECK-NEXT: 3 | void Test3::D::g() -// CHECK-NEXT: 4 | void Test3::D::h() +// CHECK-7: Vtable for 'Test3::D' (5 entries). +// CHECK-7-NEXT: 0 | offset_to_top (0) +// CHECK-7-NEXT: 1 | Test3::D RTTI +// CHECK-7-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-7-NEXT: -- (Test3::B, 0) vtable address -- +// CHECK-7-NEXT: -- (Test3::D, 0) vtable address -- +// CHECK-7-NEXT: 2 | void Test3::D::f() +// CHECK-7-NEXT: 3 | void Test3::D::g() +// CHECK-7-NEXT: 4 | void Test3::D::h() struct D : B { virtual void f(); virtual void g(); @@ -140,14 +182,14 @@ struct A { virtual R2 *f(); }; -// CHECK: Vtable for 'Test4::B' (4 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test4::B RTTI -// CHECK-NEXT: -- (Test4::A, 0) vtable address -- -// CHECK-NEXT: -- (Test4::B, 0) vtable address -- -// CHECK-NEXT: 2 | Test4::R3 *Test4::B::f() -// CHECK-NEXT: [return adjustment: 4 non-virtual] -// CHECK-NEXT: 3 | Test4::R3 *Test4::B::f() +// CHECK-8: Vtable for 'Test4::B' (4 entries). +// CHECK-8-NEXT: 0 | offset_to_top (0) +// CHECK-8-NEXT: 1 | Test4::B RTTI +// CHECK-8-NEXT: -- (Test4::A, 0) vtable address -- +// CHECK-8-NEXT: -- (Test4::B, 0) vtable address -- +// CHECK-8-NEXT: 2 | Test4::R3 *Test4::B::f() +// CHECK-8-NEXT: [return adjustment: 4 non-virtual] +// CHECK-8-NEXT: 3 | Test4::R3 *Test4::B::f() struct B : A { virtual R3 *f(); @@ -162,14 +204,14 @@ struct C { virtual V1 *f(); }; -// CHECK: Vtable for 'Test4::D' (4 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test4::D RTTI -// CHECK-NEXT: -- (Test4::C, 0) vtable address -- -// CHECK-NEXT: -- (Test4::D, 0) vtable address -- -// CHECK-NEXT: 2 | Test4::V2 *Test4::D::f() -// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] -// CHECK-NEXT: 3 | Test4::V2 *Test4::D::f() +// CHECK-9: Vtable for 'Test4::D' (4 entries). +// CHECK-9-NEXT: 0 | offset_to_top (0) +// CHECK-9-NEXT: 1 | Test4::D RTTI +// CHECK-9-NEXT: -- (Test4::C, 0) vtable address -- +// CHECK-9-NEXT: -- (Test4::D, 0) vtable address -- +// CHECK-9-NEXT: 2 | Test4::V2 *Test4::D::f() +// CHECK-9-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] +// CHECK-9-NEXT: 3 | Test4::V2 *Test4::D::f() struct D : C { virtual V2 *f(); }; @@ -178,14 +220,14 @@ V2 *D::f() { return 0; }; // Virtual result adjustments with an additional non-virtual adjustment. struct V3 : virtual R3 { int r3; }; -// CHECK: Vtable for 'Test4::E' (4 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test4::E RTTI -// CHECK-NEXT: -- (Test4::A, 0) vtable address -- -// CHECK-NEXT: -- (Test4::E, 0) vtable address -- -// CHECK-NEXT: 2 | Test4::V3 *Test4::E::f() -// CHECK-NEXT: [return adjustment: 4 non-virtual, -24 vbase offset offset] -// CHECK-NEXT: 3 | Test4::V3 *Test4::E::f() +// CHECK-10: Vtable for 'Test4::E' (4 entries). +// CHECK-10-NEXT: 0 | offset_to_top (0) +// CHECK-10-NEXT: 1 | Test4::E RTTI +// CHECK-10-NEXT: -- (Test4::A, 0) vtable address -- +// CHECK-10-NEXT: -- (Test4::E, 0) vtable address -- +// CHECK-10-NEXT: 2 | Test4::V3 *Test4::E::f() +// CHECK-10-NEXT: [return adjustment: 4 non-virtual, -24 vbase offset offset] +// CHECK-10-NEXT: 3 | Test4::V3 *Test4::E::f() struct E : A { virtual V3 *f(); @@ -194,14 +236,14 @@ V3 *E::f() { return 0;} // Test that a pure virtual member doesn't get a thunk. -// CHECK: Vtable for 'Test4::F' (5 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test4::F RTTI -// CHECK-NEXT: -- (Test4::A, 0) vtable address -- -// CHECK-NEXT: -- (Test4::F, 0) vtable address -- -// CHECK-NEXT: 2 | Test4::R3 *Test4::F::f() [pure] -// CHECK-NEXT: 3 | void Test4::F::g() -// CHECK-NEXT: 4 | Test4::R3 *Test4::F::f() [pure] +// CHECK-11: Vtable for 'Test4::F' (5 entries). +// CHECK-11-NEXT: 0 | offset_to_top (0) +// CHECK-11-NEXT: 1 | Test4::F RTTI +// CHECK-11-NEXT: -- (Test4::A, 0) vtable address -- +// CHECK-11-NEXT: -- (Test4::F, 0) vtable address -- +// CHECK-11-NEXT: 2 | Test4::R3 *Test4::F::f() [pure] +// CHECK-11-NEXT: 3 | void Test4::F::g() +// CHECK-11-NEXT: 4 | Test4::R3 *Test4::F::f() [pure] struct F : A { virtual void g(); virtual R3 *f() = 0; @@ -229,21 +271,21 @@ struct B2 : A { int b2; }; -// CHECK: Vtable for 'Test5::C' (9 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test5::C RTTI -// CHECK-NEXT: -- (Test5::A, 0) vtable address -- -// CHECK-NEXT: -- (Test5::B1, 0) vtable address -- -// CHECK-NEXT: -- (Test5::C, 0) vtable address -- -// CHECK-NEXT: 2 | void Test5::B1::f() -// CHECK-NEXT: 3 | void Test5::A::g() -// CHECK-NEXT: 4 | void Test5::C::h() -// CHECK-NEXT: 5 | offset_to_top (-16) -// CHECK-NEXT: 6 | Test5::C RTTI -// CHECK-NEXT: -- (Test5::A, 16) vtable address -- -// CHECK-NEXT: -- (Test5::B2, 16) vtable address -- -// CHECK-NEXT: 7 | void Test5::A::f() -// CHECK-NEXT: 8 | void Test5::B2::g() +// CHECK-12: Vtable for 'Test5::C' (9 entries). +// CHECK-12-NEXT: 0 | offset_to_top (0) +// CHECK-12-NEXT: 1 | Test5::C RTTI +// CHECK-12-NEXT: -- (Test5::A, 0) vtable address -- +// CHECK-12-NEXT: -- (Test5::B1, 0) vtable address -- +// CHECK-12-NEXT: -- (Test5::C, 0) vtable address -- +// CHECK-12-NEXT: 2 | void Test5::B1::f() +// CHECK-12-NEXT: 3 | void Test5::A::g() +// CHECK-12-NEXT: 4 | void Test5::C::h() +// CHECK-12-NEXT: 5 | offset_to_top (-16) +// CHECK-12-NEXT: 6 | Test5::C RTTI +// CHECK-12-NEXT: -- (Test5::A, 16) vtable address -- +// CHECK-12-NEXT: -- (Test5::B2, 16) vtable address -- +// CHECK-12-NEXT: 7 | void Test5::A::f() +// CHECK-12-NEXT: 8 | void Test5::B2::g() struct C : B1, B2 { virtual void h(); }; @@ -263,17 +305,17 @@ struct A2 { int a; }; -// CHECK: Vtable for 'Test6::C' (6 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test6::C RTTI -// CHECK-NEXT: -- (Test6::A1, 0) vtable address -- -// CHECK-NEXT: -- (Test6::C, 0) vtable address -- -// CHECK-NEXT: 2 | void Test6::C::f() -// CHECK-NEXT: 3 | offset_to_top (-16) -// CHECK-NEXT: 4 | Test6::C RTTI -// CHECK-NEXT: -- (Test6::A2, 16) vtable address -- -// CHECK-NEXT: 5 | void Test6::C::f() -// CHECK-NEXT: [this adjustment: -16 non-virtual] +// CHECK-13: Vtable for 'Test6::C' (6 entries). +// CHECK-13-NEXT: 0 | offset_to_top (0) +// CHECK-13-NEXT: 1 | Test6::C RTTI +// CHECK-13-NEXT: -- (Test6::A1, 0) vtable address -- +// CHECK-13-NEXT: -- (Test6::C, 0) vtable address -- +// CHECK-13-NEXT: 2 | void Test6::C::f() +// CHECK-13-NEXT: 3 | offset_to_top (-16) +// CHECK-13-NEXT: 4 | Test6::C RTTI +// CHECK-13-NEXT: -- (Test6::A2, 16) vtable address -- +// CHECK-13-NEXT: 5 | void Test6::C::f() +// CHECK-13-NEXT: [this adjustment: -16 non-virtual] struct C : A1, A2 { virtual void f(); }; @@ -296,25 +338,25 @@ struct B2 : A { }; struct C { virtual void c(); }; -// CHECK: Vtable for 'Test7::D' (10 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test7::D RTTI -// CHECK-NEXT: -- (Test7::C, 0) vtable address -- -// CHECK-NEXT: -- (Test7::D, 0) vtable address -- -// CHECK-NEXT: 2 | void Test7::C::c() -// CHECK-NEXT: 3 | void Test7::D::f() -// CHECK-NEXT: 4 | offset_to_top (-8) -// CHECK-NEXT: 5 | Test7::D RTTI -// CHECK-NEXT: -- (Test7::A, 8) vtable address -- -// CHECK-NEXT: -- (Test7::B1, 8) vtable address -- -// CHECK-NEXT: 6 | void Test7::D::f() -// CHECK-NEXT: [this adjustment: -8 non-virtual] -// CHECK-NEXT: 7 | offset_to_top (-24) -// CHECK-NEXT: 8 | Test7::D RTTI -// CHECK-NEXT: -- (Test7::A, 24) vtable address -- -// CHECK-NEXT: -- (Test7::B2, 24) vtable address -- -// CHECK-NEXT: 9 | void Test7::D::f() -// CHECK-NEXT: [this adjustment: -24 non-virtual] +// CHECK-14: Vtable for 'Test7::D' (10 entries). +// CHECK-14-NEXT: 0 | offset_to_top (0) +// CHECK-14-NEXT: 1 | Test7::D RTTI +// CHECK-14-NEXT: -- (Test7::C, 0) vtable address -- +// CHECK-14-NEXT: -- (Test7::D, 0) vtable address -- +// CHECK-14-NEXT: 2 | void Test7::C::c() +// CHECK-14-NEXT: 3 | void Test7::D::f() +// CHECK-14-NEXT: 4 | offset_to_top (-8) +// CHECK-14-NEXT: 5 | Test7::D RTTI +// CHECK-14-NEXT: -- (Test7::A, 8) vtable address -- +// CHECK-14-NEXT: -- (Test7::B1, 8) vtable address -- +// CHECK-14-NEXT: 6 | void Test7::D::f() +// CHECK-14-NEXT: [this adjustment: -8 non-virtual] +// CHECK-14-NEXT: 7 | offset_to_top (-24) +// CHECK-14-NEXT: 8 | Test7::D RTTI +// CHECK-14-NEXT: -- (Test7::A, 24) vtable address -- +// CHECK-14-NEXT: -- (Test7::B2, 24) vtable address -- +// CHECK-14-NEXT: 9 | void Test7::D::f() +// CHECK-14-NEXT: [this adjustment: -24 non-virtual] struct D : C, B1, B2 { virtual void f(); }; @@ -329,11 +371,11 @@ namespace Test8 { struct A { }; -// CHECK: Vtable for 'Test8::B' (3 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test8::B RTTI -// CHECK-NEXT: -- (Test8::B, 0) vtable address -- -// CHECK-NEXT: 2 | void Test8::B::f() +// CHECK-15: Vtable for 'Test8::B' (3 entries). +// CHECK-15-NEXT: 0 | offset_to_top (0) +// CHECK-15-NEXT: 1 | Test8::B RTTI +// CHECK-15-NEXT: -- (Test8::B, 0) vtable address -- +// CHECK-15-NEXT: 2 | void Test8::B::f() struct B : A { virtual void f(); }; @@ -348,13 +390,13 @@ namespace Test9 { struct A1 { int a1; }; struct A2 { int a2; }; -// CHECK: Vtable for 'Test9::B' (5 entries). -// CHECK-NEXT: 0 | vbase_offset (16) -// CHECK-NEXT: 1 | vbase_offset (12) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test9::B RTTI -// CHECK-NEXT: -- (Test9::B, 0) vtable address -- -// CHECK-NEXT: 4 | void Test9::B::f() +// CHECK-16: Vtable for 'Test9::B' (5 entries). +// CHECK-16-NEXT: 0 | vbase_offset (16) +// CHECK-16-NEXT: 1 | vbase_offset (12) +// CHECK-16-NEXT: 2 | offset_to_top (0) +// CHECK-16-NEXT: 3 | Test9::B RTTI +// CHECK-16-NEXT: -- (Test9::B, 0) vtable address -- +// CHECK-16-NEXT: 4 | void Test9::B::f() struct B : virtual A1, virtual A2 { int b; @@ -373,18 +415,18 @@ namespace Test10 { struct A1 { virtual void a1(); }; struct A2 { virtual void a2(); }; -// CHECK: Vtable for 'Test10::C' (7 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test10::C RTTI -// CHECK-NEXT: -- (Test10::A1, 0) vtable address -- -// CHECK-NEXT: -- (Test10::B, 0) vtable address -- -// CHECK-NEXT: -- (Test10::C, 0) vtable address -- -// CHECK-NEXT: 2 | void Test10::A1::a1() -// CHECK-NEXT: 3 | void Test10::C::f() -// CHECK-NEXT: 4 | offset_to_top (-8) -// CHECK-NEXT: 5 | Test10::C RTTI -// CHECK-NEXT: -- (Test10::A2, 8) vtable address -- -// CHECK-NEXT: 6 | void Test10::A2::a2() +// CHECK-17: Vtable for 'Test10::C' (7 entries). +// CHECK-17-NEXT: 0 | offset_to_top (0) +// CHECK-17-NEXT: 1 | Test10::C RTTI +// CHECK-17-NEXT: -- (Test10::A1, 0) vtable address -- +// CHECK-17-NEXT: -- (Test10::B, 0) vtable address -- +// CHECK-17-NEXT: -- (Test10::C, 0) vtable address -- +// CHECK-17-NEXT: 2 | void Test10::A1::a1() +// CHECK-17-NEXT: 3 | void Test10::C::f() +// CHECK-17-NEXT: 4 | offset_to_top (-8) +// CHECK-17-NEXT: 5 | Test10::C RTTI +// CHECK-17-NEXT: -- (Test10::A2, 8) vtable address -- +// CHECK-17-NEXT: 6 | void Test10::A2::a2() struct B : A1, A2 { int b; }; @@ -406,16 +448,16 @@ struct B : A1, virtual A2 { int b; }; -// CHECK: Vtable for 'Test11::C' (8 entries). -// CHECK-NEXT: 0 | vbase_offset (24) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test11::C RTTI -// CHECK-NEXT: -- (Test11::C, 0) vtable address -- -// CHECK-NEXT: 4 | void Test11::C::f() -// CHECK-NEXT: 5 | vbase_offset (16) -// CHECK-NEXT: 6 | offset_to_top (-8) -// CHECK-NEXT: 7 | Test11::C RTTI +// CHECK-18: Vtable for 'Test11::C' (8 entries). +// CHECK-18-NEXT: 0 | vbase_offset (24) +// CHECK-18-NEXT: 1 | vbase_offset (8) +// CHECK-18-NEXT: 2 | offset_to_top (0) +// CHECK-18-NEXT: 3 | Test11::C RTTI +// CHECK-18-NEXT: -- (Test11::C, 0) vtable address -- +// CHECK-18-NEXT: 4 | void Test11::C::f() +// CHECK-18-NEXT: 5 | vbase_offset (16) +// CHECK-18-NEXT: 6 | offset_to_top (-8) +// CHECK-18-NEXT: 7 | Test11::C RTTI struct C : virtual B { virtual void f(); }; @@ -427,32 +469,32 @@ namespace Test12 { // Test that the right vcall offsets are generated in the right order. -// CHECK: Vtable for 'Test12::B' (19 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test12::B RTTI -// CHECK-NEXT: -- (Test12::B, 0) vtable address -- -// CHECK-NEXT: 3 | void Test12::B::f() -// CHECK-NEXT: 4 | void Test12::B::a() -// CHECK-NEXT: 5 | vcall_offset (32) -// CHECK-NEXT: 6 | vcall_offset (16) -// CHECK-NEXT: 7 | vcall_offset (-8) -// CHECK-NEXT: 8 | vcall_offset (0) -// CHECK-NEXT: 9 | offset_to_top (-8) -// CHECK-NEXT: 10 | Test12::B RTTI -// CHECK-NEXT: -- (Test12::A, 8) vtable address -- -// CHECK-NEXT: -- (Test12::A1, 8) vtable address -- -// CHECK-NEXT: 11 | void Test12::A1::a1() -// CHECK-NEXT: 12 | void Test12::B::a() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] -// CHECK-NEXT: 13 | offset_to_top (-24) -// CHECK-NEXT: 14 | Test12::B RTTI -// CHECK-NEXT: -- (Test12::A2, 24) vtable address -- -// CHECK-NEXT: 15 | void Test12::A2::a2() -// CHECK-NEXT: 16 | offset_to_top (-40) -// CHECK-NEXT: 17 | Test12::B RTTI -// CHECK-NEXT: -- (Test12::A3, 40) vtable address -- -// CHECK-NEXT: 18 | void Test12::A3::a3() +// CHECK-19: Vtable for 'Test12::B' (19 entries). +// CHECK-19-NEXT: 0 | vbase_offset (8) +// CHECK-19-NEXT: 1 | offset_to_top (0) +// CHECK-19-NEXT: 2 | Test12::B RTTI +// CHECK-19-NEXT: -- (Test12::B, 0) vtable address -- +// CHECK-19-NEXT: 3 | void Test12::B::f() +// CHECK-19-NEXT: 4 | void Test12::B::a() +// CHECK-19-NEXT: 5 | vcall_offset (32) +// CHECK-19-NEXT: 6 | vcall_offset (16) +// CHECK-19-NEXT: 7 | vcall_offset (-8) +// CHECK-19-NEXT: 8 | vcall_offset (0) +// CHECK-19-NEXT: 9 | offset_to_top (-8) +// CHECK-19-NEXT: 10 | Test12::B RTTI +// CHECK-19-NEXT: -- (Test12::A, 8) vtable address -- +// CHECK-19-NEXT: -- (Test12::A1, 8) vtable address -- +// CHECK-19-NEXT: 11 | void Test12::A1::a1() +// CHECK-19-NEXT: 12 | void Test12::B::a() +// CHECK-19-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-19-NEXT: 13 | offset_to_top (-24) +// CHECK-19-NEXT: 14 | Test12::B RTTI +// CHECK-19-NEXT: -- (Test12::A2, 24) vtable address -- +// CHECK-19-NEXT: 15 | void Test12::A2::a2() +// CHECK-19-NEXT: 16 | offset_to_top (-40) +// CHECK-19-NEXT: 17 | Test12::B RTTI +// CHECK-19-NEXT: -- (Test12::A3, 40) vtable address -- +// CHECK-19-NEXT: 18 | void Test12::A3::a3() struct A1 { virtual void a1(); int a; @@ -493,16 +535,16 @@ struct B : virtual A { virtual void f(); }; -// CHECK: Vtable for 'Test13::C' (6 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vbase_offset (0) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test13::C RTTI -// CHECK-NEXT: -- (Test13::A, 0) vtable address -- -// CHECK-NEXT: -- (Test13::B, 0) vtable address -- -// CHECK-NEXT: -- (Test13::C, 0) vtable address -- -// CHECK-NEXT: 5 | void Test13::C::f() +// CHECK-20: Vtable for 'Test13::C' (6 entries). +// CHECK-20-NEXT: 0 | vbase_offset (0) +// CHECK-20-NEXT: 1 | vbase_offset (0) +// CHECK-20-NEXT: 2 | vcall_offset (0) +// CHECK-20-NEXT: 3 | offset_to_top (0) +// CHECK-20-NEXT: 4 | Test13::C RTTI +// CHECK-20-NEXT: -- (Test13::A, 0) vtable address -- +// CHECK-20-NEXT: -- (Test13::B, 0) vtable address -- +// CHECK-20-NEXT: -- (Test13::C, 0) vtable address -- +// CHECK-20-NEXT: 5 | void Test13::C::f() struct C : virtual B, virtual A { virtual void f(); }; @@ -522,16 +564,16 @@ struct B : A { }; struct C : virtual B { }; -// CHECK: Vtable for 'Test14::D' (5 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test14::D RTTI -// CHECK-NEXT: -- (Test14::A, 0) vtable address -- -// CHECK-NEXT: -- (Test14::B, 0) vtable address -- -// CHECK-NEXT: -- (Test14::C, 0) vtable address -- -// CHECK-NEXT: -- (Test14::D, 0) vtable address -- -// CHECK-NEXT: 4 | void Test14::D::f() +// CHECK-21: Vtable for 'Test14::D' (5 entries). +// CHECK-21-NEXT: 0 | vbase_offset (0) +// CHECK-21-NEXT: 1 | vcall_offset (0) +// CHECK-21-NEXT: 2 | offset_to_top (0) +// CHECK-21-NEXT: 3 | Test14::D RTTI +// CHECK-21-NEXT: -- (Test14::A, 0) vtable address -- +// CHECK-21-NEXT: -- (Test14::B, 0) vtable address -- +// CHECK-21-NEXT: -- (Test14::C, 0) vtable address -- +// CHECK-21-NEXT: -- (Test14::D, 0) vtable address -- +// CHECK-21-NEXT: 4 | void Test14::D::f() struct D : C, virtual B { virtual void f(); }; @@ -547,22 +589,22 @@ struct B { virtual void b(); }; struct C : virtual B { }; -// CHECK: Vtable for 'Test15::D' (11 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test15::D RTTI -// CHECK-NEXT: -- (Test15::A, 0) vtable address -- -// CHECK-NEXT: -- (Test15::D, 0) vtable address -- -// CHECK-NEXT: 4 | void Test15::A::a() -// CHECK-NEXT: 5 | void Test15::D::f() -// CHECK-NEXT: 6 | vbase_offset (0) -// CHECK-NEXT: 7 | vcall_offset (0) -// CHECK-NEXT: 8 | offset_to_top (-8) -// CHECK-NEXT: 9 | Test15::D RTTI -// CHECK-NEXT: -- (Test15::B, 8) vtable address -- -// CHECK-NEXT: -- (Test15::C, 8) vtable address -- -// CHECK-NEXT: 10 | void Test15::B::b() +// CHECK-22: Vtable for 'Test15::D' (11 entries). +// CHECK-22-NEXT: 0 | vbase_offset (8) +// CHECK-22-NEXT: 1 | vbase_offset (8) +// CHECK-22-NEXT: 2 | offset_to_top (0) +// CHECK-22-NEXT: 3 | Test15::D RTTI +// CHECK-22-NEXT: -- (Test15::A, 0) vtable address -- +// CHECK-22-NEXT: -- (Test15::D, 0) vtable address -- +// CHECK-22-NEXT: 4 | void Test15::A::a() +// CHECK-22-NEXT: 5 | void Test15::D::f() +// CHECK-22-NEXT: 6 | vbase_offset (0) +// CHECK-22-NEXT: 7 | vcall_offset (0) +// CHECK-22-NEXT: 8 | offset_to_top (-8) +// CHECK-22-NEXT: 9 | Test15::D RTTI +// CHECK-22-NEXT: -- (Test15::B, 8) vtable address -- +// CHECK-22-NEXT: -- (Test15::C, 8) vtable address -- +// CHECK-22-NEXT: 10 | void Test15::B::b() struct D : A, virtual B, virtual C { virtual void f(); }; @@ -579,30 +621,30 @@ struct B { virtual ~B(); }; struct C : A, B { virtual ~C(); }; -// CHECK: Vtable for 'Test16::D' (15 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test16::D RTTI -// CHECK-NEXT: -- (Test16::D, 0) vtable address -- -// CHECK-NEXT: 3 | void Test16::D::f() -// CHECK-NEXT: 4 | Test16::D::~D() [complete] -// CHECK-NEXT: 5 | Test16::D::~D() [deleting] -// CHECK-NEXT: 6 | vcall_offset (-8) -// CHECK-NEXT: 7 | offset_to_top (-8) -// CHECK-NEXT: 8 | Test16::D RTTI -// CHECK-NEXT: -- (Test16::A, 8) vtable address -- -// CHECK-NEXT: -- (Test16::C, 8) vtable address -- -// CHECK-NEXT: 9 | Test16::D::~D() [complete] -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] -// CHECK-NEXT: 10 | Test16::D::~D() [deleting] -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] -// CHECK-NEXT: 11 | offset_to_top (-16) -// CHECK-NEXT: 12 | Test16::D RTTI -// CHECK-NEXT: -- (Test16::B, 16) vtable address -- -// CHECK-NEXT: 13 | Test16::D::~D() [complete] -// CHECK-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] -// CHECK-NEXT: 14 | Test16::D::~D() [deleting] -// CHECK-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] +// CHECK-23: Vtable for 'Test16::D' (15 entries). +// CHECK-23-NEXT: 0 | vbase_offset (8) +// CHECK-23-NEXT: 1 | offset_to_top (0) +// CHECK-23-NEXT: 2 | Test16::D RTTI +// CHECK-23-NEXT: -- (Test16::D, 0) vtable address -- +// CHECK-23-NEXT: 3 | void Test16::D::f() +// CHECK-23-NEXT: 4 | Test16::D::~D() [complete] +// CHECK-23-NEXT: 5 | Test16::D::~D() [deleting] +// CHECK-23-NEXT: 6 | vcall_offset (-8) +// CHECK-23-NEXT: 7 | offset_to_top (-8) +// CHECK-23-NEXT: 8 | Test16::D RTTI +// CHECK-23-NEXT: -- (Test16::A, 8) vtable address -- +// CHECK-23-NEXT: -- (Test16::C, 8) vtable address -- +// CHECK-23-NEXT: 9 | Test16::D::~D() [complete] +// CHECK-23-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-23-NEXT: 10 | Test16::D::~D() [deleting] +// CHECK-23-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-23-NEXT: 11 | offset_to_top (-16) +// CHECK-23-NEXT: 12 | Test16::D RTTI +// CHECK-23-NEXT: -- (Test16::B, 16) vtable address -- +// CHECK-23-NEXT: 13 | Test16::D::~D() [complete] +// CHECK-23-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] +// CHECK-23-NEXT: 14 | Test16::D::~D() [deleting] +// CHECK-23-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] struct D : virtual C { virtual void f(); }; @@ -618,26 +660,26 @@ struct B : virtual A { virtual void f(); }; struct C : virtual A { virtual void f(); }; struct D : virtual B, virtual C { virtual void f(); }; -// CHECK: Vtable for 'Test17::E' (13 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | vbase_offset (0) -// CHECK-NEXT: 3 | vbase_offset (0) -// CHECK-NEXT: 4 | vcall_offset (0) -// CHECK-NEXT: 5 | offset_to_top (0) -// CHECK-NEXT: 6 | Test17::E RTTI -// CHECK-NEXT: -- (Test17::A, 0) vtable address -- -// CHECK-NEXT: -- (Test17::B, 0) vtable address -- -// CHECK-NEXT: -- (Test17::D, 0) vtable address -- -// CHECK-NEXT: -- (Test17::E, 0) vtable address -- -// CHECK-NEXT: 7 | void Test17::E::f() -// CHECK-NEXT: 8 | vbase_offset (-8) -// CHECK-NEXT: 9 | vcall_offset (-8) -// CHECK-NEXT: 10 | offset_to_top (-8) -// CHECK-NEXT: 11 | Test17::E RTTI -// CHECK-NEXT: -- (Test17::C, 8) vtable address -- -// CHECK-NEXT: 12 | void Test17::E::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-24: Vtable for 'Test17::E' (13 entries). +// CHECK-24-NEXT: 0 | vbase_offset (0) +// CHECK-24-NEXT: 1 | vbase_offset (8) +// CHECK-24-NEXT: 2 | vbase_offset (0) +// CHECK-24-NEXT: 3 | vbase_offset (0) +// CHECK-24-NEXT: 4 | vcall_offset (0) +// CHECK-24-NEXT: 5 | offset_to_top (0) +// CHECK-24-NEXT: 6 | Test17::E RTTI +// CHECK-24-NEXT: -- (Test17::A, 0) vtable address -- +// CHECK-24-NEXT: -- (Test17::B, 0) vtable address -- +// CHECK-24-NEXT: -- (Test17::D, 0) vtable address -- +// CHECK-24-NEXT: -- (Test17::E, 0) vtable address -- +// CHECK-24-NEXT: 7 | void Test17::E::f() +// CHECK-24-NEXT: 8 | vbase_offset (-8) +// CHECK-24-NEXT: 9 | vcall_offset (-8) +// CHECK-24-NEXT: 10 | offset_to_top (-8) +// CHECK-24-NEXT: 11 | Test17::E RTTI +// CHECK-24-NEXT: -- (Test17::C, 8) vtable address -- +// CHECK-24-NEXT: 12 | void Test17::E::f() +// CHECK-24-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] class E : virtual D { virtual void f(); }; @@ -662,97 +704,97 @@ struct C : A, B { virtual void g(); }; -// CHECK: Vtable for 'Test18::D' (24 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | vbase_offset (0) -// CHECK-NEXT: 2 | vbase_offset (0) -// CHECK-NEXT: 3 | vcall_offset (8) -// CHECK-NEXT: 4 | vcall_offset (0) -// CHECK-NEXT: 5 | offset_to_top (0) -// CHECK-NEXT: 6 | Test18::D RTTI -// CHECK-NEXT: -- (Test18::A, 0) vtable address -- -// CHECK-NEXT: -- (Test18::B, 0) vtable address -- -// CHECK-NEXT: -- (Test18::D, 0) vtable address -- -// CHECK-NEXT: 7 | void Test18::D::f() -// CHECK-NEXT: 8 | void Test18::C::g() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] -// CHECK-NEXT: 9 | void Test18::D::h() -// CHECK-NEXT: 10 | vcall_offset (0) -// CHECK-NEXT: 11 | vcall_offset (-8) -// CHECK-NEXT: 12 | vbase_offset (-8) -// CHECK-NEXT: 13 | offset_to_top (-8) -// CHECK-NEXT: 14 | Test18::D RTTI -// CHECK-NEXT: -- (Test18::A, 8) vtable address -- -// CHECK-NEXT: -- (Test18::C, 8) vtable address -- -// CHECK-NEXT: 15 | void Test18::D::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] -// CHECK-NEXT: 16 | void Test18::C::g() -// CHECK-NEXT: 17 | vbase_offset (-16) -// CHECK-NEXT: 18 | vcall_offset (-8) -// CHECK-NEXT: 19 | vcall_offset (-16) -// CHECK-NEXT: 20 | offset_to_top (-16) -// CHECK-NEXT: 21 | Test18::D RTTI -// CHECK-NEXT: -- (Test18::B, 16) vtable address -- -// CHECK-NEXT: 22 | void Test18::D::f() -// CHECK-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] -// CHECK-NEXT: 23 | [unused] void Test18::C::g() - -// CHECK: Construction vtable for ('Test18::B', 0) in 'Test18::D' (7 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test18::B RTTI -// CHECK-NEXT: -- (Test18::A, 0) vtable address -- -// CHECK-NEXT: -- (Test18::B, 0) vtable address -- -// CHECK-NEXT: 5 | void Test18::B::f() -// CHECK-NEXT: 6 | void Test18::A::g() - -// CHECK: Construction vtable for ('Test18::C', 8) in 'Test18::D' (20 entries). -// CHECK-NEXT: 0 | vcall_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | vbase_offset (-8) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test18::C RTTI -// CHECK-NEXT: -- (Test18::A, 8) vtable address -- -// CHECK-NEXT: -- (Test18::C, 8) vtable address -- -// CHECK-NEXT: 5 | void Test18::A::f() -// CHECK-NEXT: 6 | void Test18::C::g() -// CHECK-NEXT: 7 | vbase_offset (-16) -// CHECK-NEXT: 8 | vcall_offset (-8) -// CHECK-NEXT: 9 | vcall_offset (0) -// CHECK-NEXT: 10 | offset_to_top (-8) -// CHECK-NEXT: 11 | Test18::C RTTI -// CHECK-NEXT: -- (Test18::B, 16) vtable address -- -// CHECK-NEXT: 12 | void Test18::B::f() -// CHECK-NEXT: 13 | [unused] void Test18::C::g() -// CHECK-NEXT: 14 | vcall_offset (8) -// CHECK-NEXT: 15 | vcall_offset (16) -// CHECK-NEXT: 16 | offset_to_top (8) -// CHECK-NEXT: 17 | Test18::C RTTI -// CHECK-NEXT: -- (Test18::A, 0) vtable address -- -// CHECK-NEXT: 18 | void Test18::B::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] -// CHECK-NEXT: 19 | void Test18::C::g() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] - -// CHECK: Construction vtable for ('Test18::B', 16) in 'Test18::D' (13 entries). -// CHECK-NEXT: 0 | vbase_offset (-16) -// CHECK-NEXT: 1 | vcall_offset (-16) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test18::B RTTI -// CHECK-NEXT: -- (Test18::B, 16) vtable address -- -// CHECK-NEXT: 5 | void Test18::B::f() -// CHECK-NEXT: 6 | [unused] void Test18::A::g() -// CHECK-NEXT: 7 | vcall_offset (0) -// CHECK-NEXT: 8 | vcall_offset (16) -// CHECK-NEXT: 9 | offset_to_top (16) -// CHECK-NEXT: 10 | Test18::B RTTI -// CHECK-NEXT: -- (Test18::A, 0) vtable address -- -// CHECK-NEXT: 11 | void Test18::B::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] -// CHECK-NEXT: 12 | void Test18::A::g() +// CHECK-25: Vtable for 'Test18::D' (24 entries). +// CHECK-25-NEXT: 0 | vbase_offset (8) +// CHECK-25-NEXT: 1 | vbase_offset (0) +// CHECK-25-NEXT: 2 | vbase_offset (0) +// CHECK-25-NEXT: 3 | vcall_offset (8) +// CHECK-25-NEXT: 4 | vcall_offset (0) +// CHECK-25-NEXT: 5 | offset_to_top (0) +// CHECK-25-NEXT: 6 | Test18::D RTTI +// CHECK-25-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-25-NEXT: -- (Test18::B, 0) vtable address -- +// CHECK-25-NEXT: -- (Test18::D, 0) vtable address -- +// CHECK-25-NEXT: 7 | void Test18::D::f() +// CHECK-25-NEXT: 8 | void Test18::C::g() +// CHECK-25-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-25-NEXT: 9 | void Test18::D::h() +// CHECK-25-NEXT: 10 | vcall_offset (0) +// CHECK-25-NEXT: 11 | vcall_offset (-8) +// CHECK-25-NEXT: 12 | vbase_offset (-8) +// CHECK-25-NEXT: 13 | offset_to_top (-8) +// CHECK-25-NEXT: 14 | Test18::D RTTI +// CHECK-25-NEXT: -- (Test18::A, 8) vtable address -- +// CHECK-25-NEXT: -- (Test18::C, 8) vtable address -- +// CHECK-25-NEXT: 15 | void Test18::D::f() +// CHECK-25-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-25-NEXT: 16 | void Test18::C::g() +// CHECK-25-NEXT: 17 | vbase_offset (-16) +// CHECK-25-NEXT: 18 | vcall_offset (-8) +// CHECK-25-NEXT: 19 | vcall_offset (-16) +// CHECK-25-NEXT: 20 | offset_to_top (-16) +// CHECK-25-NEXT: 21 | Test18::D RTTI +// CHECK-25-NEXT: -- (Test18::B, 16) vtable address -- +// CHECK-25-NEXT: 22 | void Test18::D::f() +// CHECK-25-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] +// CHECK-25-NEXT: 23 | [unused] void Test18::C::g() + +// CHECK-25: Construction vtable for ('Test18::B', 0) in 'Test18::D' (7 entries). +// CHECK-25-NEXT: 0 | vbase_offset (0) +// CHECK-25-NEXT: 1 | vcall_offset (0) +// CHECK-25-NEXT: 2 | vcall_offset (0) +// CHECK-25-NEXT: 3 | offset_to_top (0) +// CHECK-25-NEXT: 4 | Test18::B RTTI +// CHECK-25-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-25-NEXT: -- (Test18::B, 0) vtable address -- +// CHECK-25-NEXT: 5 | void Test18::B::f() +// CHECK-25-NEXT: 6 | void Test18::A::g() + +// CHECK-25: Construction vtable for ('Test18::C', 8) in 'Test18::D' (20 entries). +// CHECK-25-NEXT: 0 | vcall_offset (0) +// CHECK-25-NEXT: 1 | vcall_offset (0) +// CHECK-25-NEXT: 2 | vbase_offset (-8) +// CHECK-25-NEXT: 3 | offset_to_top (0) +// CHECK-25-NEXT: 4 | Test18::C RTTI +// CHECK-25-NEXT: -- (Test18::A, 8) vtable address -- +// CHECK-25-NEXT: -- (Test18::C, 8) vtable address -- +// CHECK-25-NEXT: 5 | void Test18::A::f() +// CHECK-25-NEXT: 6 | void Test18::C::g() +// CHECK-25-NEXT: 7 | vbase_offset (-16) +// CHECK-25-NEXT: 8 | vcall_offset (-8) +// CHECK-25-NEXT: 9 | vcall_offset (0) +// CHECK-25-NEXT: 10 | offset_to_top (-8) +// CHECK-25-NEXT: 11 | Test18::C RTTI +// CHECK-25-NEXT: -- (Test18::B, 16) vtable address -- +// CHECK-25-NEXT: 12 | void Test18::B::f() +// CHECK-25-NEXT: 13 | [unused] void Test18::C::g() +// CHECK-25-NEXT: 14 | vcall_offset (8) +// CHECK-25-NEXT: 15 | vcall_offset (16) +// CHECK-25-NEXT: 16 | offset_to_top (8) +// CHECK-25-NEXT: 17 | Test18::C RTTI +// CHECK-25-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-25-NEXT: 18 | void Test18::B::f() +// CHECK-25-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-25-NEXT: 19 | void Test18::C::g() +// CHECK-25-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] + +// CHECK-25: Construction vtable for ('Test18::B', 16) in 'Test18::D' (13 entries). +// CHECK-25-NEXT: 0 | vbase_offset (-16) +// CHECK-25-NEXT: 1 | vcall_offset (-16) +// CHECK-25-NEXT: 2 | vcall_offset (0) +// CHECK-25-NEXT: 3 | offset_to_top (0) +// CHECK-25-NEXT: 4 | Test18::B RTTI +// CHECK-25-NEXT: -- (Test18::B, 16) vtable address -- +// CHECK-25-NEXT: 5 | void Test18::B::f() +// CHECK-25-NEXT: 6 | [unused] void Test18::A::g() +// CHECK-25-NEXT: 7 | vcall_offset (0) +// CHECK-25-NEXT: 8 | vcall_offset (16) +// CHECK-25-NEXT: 9 | offset_to_top (16) +// CHECK-25-NEXT: 10 | Test18::B RTTI +// CHECK-25-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-25-NEXT: 11 | void Test18::B::f() +// CHECK-25-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-25-NEXT: 12 | void Test18::A::g() struct D : virtual B, virtual C, virtual A { virtual void f(); @@ -782,27 +824,27 @@ struct C { virtual void c(); }; -// CHECK: Vtable for 'Test19::D' (13 entries). -// CHECK-NEXT: 0 | vbase_offset (24) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test19::D RTTI -// CHECK-NEXT: -- (Test19::C, 0) vtable address -- -// CHECK-NEXT: -- (Test19::D, 0) vtable address -- -// CHECK-NEXT: 3 | void Test19::C::c() -// CHECK-NEXT: 4 | void Test19::D::f() -// CHECK-NEXT: 5 | offset_to_top (-8) -// CHECK-NEXT: 6 | Test19::D RTTI -// CHECK-NEXT: -- (Test19::A, 8) vtable address -- -// CHECK-NEXT: -- (Test19::B, 8) vtable address -- -// CHECK-NEXT: 7 | void Test19::D::f() -// CHECK-NEXT: [this adjustment: -8 non-virtual] -// CHECK-NEXT: 8 | void Test19::B::g() -// CHECK-NEXT: 9 | vcall_offset (-24) -// CHECK-NEXT: 10 | offset_to_top (-24) -// CHECK-NEXT: 11 | Test19::D RTTI -// CHECK-NEXT: -- (Test19::A, 24) vtable address -- -// CHECK-NEXT: 12 | void Test19::D::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-26: Vtable for 'Test19::D' (13 entries). +// CHECK-26-NEXT: 0 | vbase_offset (24) +// CHECK-26-NEXT: 1 | offset_to_top (0) +// CHECK-26-NEXT: 2 | Test19::D RTTI +// CHECK-26-NEXT: -- (Test19::C, 0) vtable address -- +// CHECK-26-NEXT: -- (Test19::D, 0) vtable address -- +// CHECK-26-NEXT: 3 | void Test19::C::c() +// CHECK-26-NEXT: 4 | void Test19::D::f() +// CHECK-26-NEXT: 5 | offset_to_top (-8) +// CHECK-26-NEXT: 6 | Test19::D RTTI +// CHECK-26-NEXT: -- (Test19::A, 8) vtable address -- +// CHECK-26-NEXT: -- (Test19::B, 8) vtable address -- +// CHECK-26-NEXT: 7 | void Test19::D::f() +// CHECK-26-NEXT: [this adjustment: -8 non-virtual] +// CHECK-26-NEXT: 8 | void Test19::B::g() +// CHECK-26-NEXT: 9 | vcall_offset (-24) +// CHECK-26-NEXT: 10 | offset_to_top (-24) +// CHECK-26-NEXT: 11 | Test19::D RTTI +// CHECK-26-NEXT: -- (Test19::A, 24) vtable address -- +// CHECK-26-NEXT: 12 | void Test19::D::f() +// CHECK-26-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] struct D : C, B, virtual A { virtual void f(); }; @@ -821,20 +863,20 @@ struct A { struct B : A { }; -// CHECK: Vtable for 'Test20::C' (9 entries). -// CHECK-NEXT: 0 | offset_to_top (0) -// CHECK-NEXT: 1 | Test20::C RTTI -// CHECK-NEXT: -- (Test20::A, 0) vtable address -- -// CHECK-NEXT: -- (Test20::C, 0) vtable address -- -// CHECK-NEXT: 2 | void Test20::C::f() [pure] -// CHECK-NEXT: 3 | void Test20::A::g() -// CHECK-NEXT: 4 | void Test20::C::h() -// CHECK-NEXT: 5 | offset_to_top (-8) -// CHECK-NEXT: 6 | Test20::C RTTI -// CHECK-NEXT: -- (Test20::A, 8) vtable address -- -// CHECK-NEXT: -- (Test20::B, 8) vtable address -- -// CHECK-NEXT: 7 | void Test20::C::f() [pure] -// CHECK-NEXT: 8 | void Test20::A::g() +// CHECK-27: Vtable for 'Test20::C' (9 entries). +// CHECK-27-NEXT: 0 | offset_to_top (0) +// CHECK-27-NEXT: 1 | Test20::C RTTI +// CHECK-27-NEXT: -- (Test20::A, 0) vtable address -- +// CHECK-27-NEXT: -- (Test20::C, 0) vtable address -- +// CHECK-27-NEXT: 2 | void Test20::C::f() [pure] +// CHECK-27-NEXT: 3 | void Test20::A::g() +// CHECK-27-NEXT: 4 | void Test20::C::h() +// CHECK-27-NEXT: 5 | offset_to_top (-8) +// CHECK-27-NEXT: 6 | Test20::C RTTI +// CHECK-27-NEXT: -- (Test20::A, 8) vtable address -- +// CHECK-27-NEXT: -- (Test20::B, 8) vtable address -- +// CHECK-27-NEXT: 7 | void Test20::C::f() [pure] +// CHECK-27-NEXT: 8 | void Test20::A::g() struct C : A, B { virtual void f() = 0; virtual void h(); @@ -856,36 +898,36 @@ class D : virtual C { }; class E : virtual C { }; -// CHECK: Vtable for 'Test21::F' (16 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | vbase_offset (0) -// CHECK-NEXT: 2 | vbase_offset (0) -// CHECK-NEXT: 3 | vbase_offset (0) -// CHECK-NEXT: 4 | vbase_offset (0) -// CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (0) -// CHECK-NEXT: 7 | Test21::F RTTI -// CHECK-NEXT: -- (Test21::A, 0) vtable address -- -// CHECK-NEXT: -- (Test21::B, 0) vtable address -- -// CHECK-NEXT: -- (Test21::C, 0) vtable address -- -// CHECK-NEXT: -- (Test21::D, 0) vtable address -- -// CHECK-NEXT: -- (Test21::F, 0) vtable address -- -// CHECK-NEXT: 8 | void Test21::F::f() -// CHECK-NEXT: 9 | vbase_offset (-8) -// CHECK-NEXT: 10 | vbase_offset (-8) -// CHECK-NEXT: 11 | vbase_offset (-8) -// CHECK-NEXT: 12 | vcall_offset (-8) -// CHECK-NEXT: 13 | offset_to_top (-8) -// CHECK-NEXT: 14 | Test21::F RTTI -// CHECK-NEXT: -- (Test21::E, 8) vtable address -- -// CHECK-NEXT: 15 | [unused] void Test21::F::f() +// CHECK-28: Vtable for 'Test21::F' (16 entries). +// CHECK-28-NEXT: 0 | vbase_offset (8) +// CHECK-28-NEXT: 1 | vbase_offset (0) +// CHECK-28-NEXT: 2 | vbase_offset (0) +// CHECK-28-NEXT: 3 | vbase_offset (0) +// CHECK-28-NEXT: 4 | vbase_offset (0) +// CHECK-28-NEXT: 5 | vcall_offset (0) +// CHECK-28-NEXT: 6 | offset_to_top (0) +// CHECK-28-NEXT: 7 | Test21::F RTTI +// CHECK-28-NEXT: -- (Test21::A, 0) vtable address -- +// CHECK-28-NEXT: -- (Test21::B, 0) vtable address -- +// CHECK-28-NEXT: -- (Test21::C, 0) vtable address -- +// CHECK-28-NEXT: -- (Test21::D, 0) vtable address -- +// CHECK-28-NEXT: -- (Test21::F, 0) vtable address -- +// CHECK-28-NEXT: 8 | void Test21::F::f() +// CHECK-28-NEXT: 9 | vbase_offset (-8) +// CHECK-28-NEXT: 10 | vbase_offset (-8) +// CHECK-28-NEXT: 11 | vbase_offset (-8) +// CHECK-28-NEXT: 12 | vcall_offset (-8) +// CHECK-28-NEXT: 13 | offset_to_top (-8) +// CHECK-28-NEXT: 14 | Test21::F RTTI +// CHECK-28-NEXT: -- (Test21::E, 8) vtable address -- +// CHECK-28-NEXT: 15 | [unused] void Test21::F::f() // -// CHECK: Virtual base offset offsets for 'Test21::F' (5 entries). -// CHECK-NEXT: Test21::A | -32 -// CHECK-NEXT: Test21::B | -40 -// CHECK-NEXT: Test21::C | -48 -// CHECK-NEXT: Test21::D | -56 -// CHECK-NEXT: Test21::E | -64 +// CHECK-28: Virtual base offset offsets for 'Test21::F' (5 entries). +// CHECK-28-NEXT: Test21::A | -32 +// CHECK-28-NEXT: Test21::B | -40 +// CHECK-28-NEXT: Test21::C | -48 +// CHECK-28-NEXT: Test21::D | -56 +// CHECK-28-NEXT: Test21::E | -64 class F : virtual D, virtual E { virtual void f(); }; @@ -904,22 +946,22 @@ struct V2 : virtual V1 { int v2; }; -// CHECK: Vtable for 'Test22::C' (8 entries). -// CHECK-NEXT: 0 | vbase_offset (16) -// CHECK-NEXT: 1 | vbase_offset (12) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test22::C RTTI -// CHECK-NEXT: -- (Test22::C, 0) vtable address -- -// CHECK-NEXT: 4 | void Test22::C::f() -// CHECK-NEXT: 5 | vbase_offset (-4) -// CHECK-NEXT: 6 | offset_to_top (-16) -// CHECK-NEXT: 7 | Test22::C RTTI -// CHECK-NEXT: -- (Test22::V2, 16) vtable address -- +// CHECK-29: Vtable for 'Test22::C' (8 entries). +// CHECK-29-NEXT: 0 | vbase_offset (16) +// CHECK-29-NEXT: 1 | vbase_offset (12) +// CHECK-29-NEXT: 2 | offset_to_top (0) +// CHECK-29-NEXT: 3 | Test22::C RTTI +// CHECK-29-NEXT: -- (Test22::C, 0) vtable address -- +// CHECK-29-NEXT: 4 | void Test22::C::f() +// CHECK-29-NEXT: 5 | vbase_offset (-4) +// CHECK-29-NEXT: 6 | offset_to_top (-16) +// CHECK-29-NEXT: 7 | Test22::C RTTI +// CHECK-29-NEXT: -- (Test22::V2, 16) vtable address -- -// CHECK: Construction vtable for ('Test22::V2', 16) in 'Test22::C' (3 entries). -// CHECK-NEXT: 0 | vbase_offset (-4) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test22::V2 RTTI +// CHECK-29: Construction vtable for ('Test22::V2', 16) in 'Test22::C' (3 entries). +// CHECK-29-NEXT: 0 | vbase_offset (-4) +// CHECK-29-NEXT: 1 | offset_to_top (0) +// CHECK-29-NEXT: 2 | Test22::V2 RTTI struct C : virtual V1, virtual V2 { int c; @@ -943,34 +985,34 @@ struct C : A, virtual B { int c; }; -// CHECK: Vtable for 'Test23::D' (7 entries). -// CHECK-NEXT: 0 | vbase_offset (20) -// CHECK-NEXT: 1 | vbase_offset (24) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test23::D RTTI -// CHECK-NEXT: -- (Test23::C, 0) vtable address -- -// CHECK-NEXT: -- (Test23::D, 0) vtable address -- -// CHECK-NEXT: 4 | vbase_offset (-4) -// CHECK-NEXT: 5 | offset_to_top (-24) -// CHECK-NEXT: 6 | Test23::D RTTI -// CHECK-NEXT: -- (Test23::B, 24) vtable address -- - -// CHECK: Construction vtable for ('Test23::C', 0) in 'Test23::D' (7 entries). -// CHECK-NEXT: 0 | vbase_offset (20) -// CHECK-NEXT: 1 | vbase_offset (24) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test23::C RTTI -// CHECK-NEXT: -- (Test23::C, 0) vtable address -- -// CHECK-NEXT: 4 | vbase_offset (-4) -// CHECK-NEXT: 5 | offset_to_top (-24) -// CHECK-NEXT: 6 | Test23::C RTTI -// CHECK-NEXT: -- (Test23::B, 24) vtable address -- - -// CHECK: Construction vtable for ('Test23::B', 24) in 'Test23::D' (3 entries). -// CHECK-NEXT: 0 | vbase_offset (-4) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test23::B RTTI -// CHECK-NEXT: -- (Test23::B, 24) vtable address -- +// CHECK-30: Vtable for 'Test23::D' (7 entries). +// CHECK-30-NEXT: 0 | vbase_offset (20) +// CHECK-30-NEXT: 1 | vbase_offset (24) +// CHECK-30-NEXT: 2 | offset_to_top (0) +// CHECK-30-NEXT: 3 | Test23::D RTTI +// CHECK-30-NEXT: -- (Test23::C, 0) vtable address -- +// CHECK-30-NEXT: -- (Test23::D, 0) vtable address -- +// CHECK-30-NEXT: 4 | vbase_offset (-4) +// CHECK-30-NEXT: 5 | offset_to_top (-24) +// CHECK-30-NEXT: 6 | Test23::D RTTI +// CHECK-30-NEXT: -- (Test23::B, 24) vtable address -- + +// CHECK-30: Construction vtable for ('Test23::C', 0) in 'Test23::D' (7 entries). +// CHECK-30-NEXT: 0 | vbase_offset (20) +// CHECK-30-NEXT: 1 | vbase_offset (24) +// CHECK-30-NEXT: 2 | offset_to_top (0) +// CHECK-30-NEXT: 3 | Test23::C RTTI +// CHECK-30-NEXT: -- (Test23::C, 0) vtable address -- +// CHECK-30-NEXT: 4 | vbase_offset (-4) +// CHECK-30-NEXT: 5 | offset_to_top (-24) +// CHECK-30-NEXT: 6 | Test23::C RTTI +// CHECK-30-NEXT: -- (Test23::B, 24) vtable address -- + +// CHECK-30: Construction vtable for ('Test23::B', 24) in 'Test23::D' (3 entries). +// CHECK-30-NEXT: 0 | vbase_offset (-4) +// CHECK-30-NEXT: 1 | offset_to_top (0) +// CHECK-30-NEXT: 2 | Test23::B RTTI +// CHECK-30-NEXT: -- (Test23::B, 24) vtable address -- struct D : virtual A, virtual B, C { int d; @@ -978,7 +1020,7 @@ struct D : virtual A, virtual B, C { void f(); }; void D::f() { } - + D d; } namespace Test24 { @@ -992,43 +1034,43 @@ struct A { struct B : virtual A { }; struct C : virtual A { }; -// CHECK: Vtable for 'Test24::D' (10 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test24::D RTTI -// CHECK-NEXT: -- (Test24::A, 0) vtable address -- -// CHECK-NEXT: -- (Test24::B, 0) vtable address -- -// CHECK-NEXT: -- (Test24::D, 0) vtable address -- -// CHECK-NEXT: 4 | void Test24::D::f() -// CHECK-NEXT: 5 | vbase_offset (-8) -// CHECK-NEXT: 6 | vcall_offset (-8) -// CHECK-NEXT: 7 | offset_to_top (-8) -// CHECK-NEXT: 8 | Test24::D RTTI -// CHECK-NEXT: -- (Test24::C, 8) vtable address -- -// CHECK-NEXT: 9 | [unused] void Test24::D::f() - -// CHECK: Construction vtable for ('Test24::B', 0) in 'Test24::D' (5 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test24::B RTTI -// CHECK-NEXT: -- (Test24::A, 0) vtable address -- -// CHECK-NEXT: -- (Test24::B, 0) vtable address -- -// CHECK-NEXT: 4 | void Test24::A::f() - -// CHECK: Construction vtable for ('Test24::C', 8) in 'Test24::D' (9 entries). -// CHECK-NEXT: 0 | vbase_offset (-8) -// CHECK-NEXT: 1 | vcall_offset (-8) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test24::C RTTI -// CHECK-NEXT: -- (Test24::C, 8) vtable address -- -// CHECK-NEXT: 4 | [unused] void Test24::A::f() -// CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (8) -// CHECK-NEXT: 7 | Test24::C RTTI -// CHECK-NEXT: -- (Test24::A, 0) vtable address -- -// CHECK-NEXT: 8 | void Test24::A::f() +// CHECK-31: Vtable for 'Test24::D' (10 entries). +// CHECK-31-NEXT: 0 | vbase_offset (0) +// CHECK-31-NEXT: 1 | vcall_offset (0) +// CHECK-31-NEXT: 2 | offset_to_top (0) +// CHECK-31-NEXT: 3 | Test24::D RTTI +// CHECK-31-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-31-NEXT: -- (Test24::B, 0) vtable address -- +// CHECK-31-NEXT: -- (Test24::D, 0) vtable address -- +// CHECK-31-NEXT: 4 | void Test24::D::f() +// CHECK-31-NEXT: 5 | vbase_offset (-8) +// CHECK-31-NEXT: 6 | vcall_offset (-8) +// CHECK-31-NEXT: 7 | offset_to_top (-8) +// CHECK-31-NEXT: 8 | Test24::D RTTI +// CHECK-31-NEXT: -- (Test24::C, 8) vtable address -- +// CHECK-31-NEXT: 9 | [unused] void Test24::D::f() + +// CHECK-31: Construction vtable for ('Test24::B', 0) in 'Test24::D' (5 entries). +// CHECK-31-NEXT: 0 | vbase_offset (0) +// CHECK-31-NEXT: 1 | vcall_offset (0) +// CHECK-31-NEXT: 2 | offset_to_top (0) +// CHECK-31-NEXT: 3 | Test24::B RTTI +// CHECK-31-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-31-NEXT: -- (Test24::B, 0) vtable address -- +// CHECK-31-NEXT: 4 | void Test24::A::f() + +// CHECK-31: Construction vtable for ('Test24::C', 8) in 'Test24::D' (9 entries). +// CHECK-31-NEXT: 0 | vbase_offset (-8) +// CHECK-31-NEXT: 1 | vcall_offset (-8) +// CHECK-31-NEXT: 2 | offset_to_top (0) +// CHECK-31-NEXT: 3 | Test24::C RTTI +// CHECK-31-NEXT: -- (Test24::C, 8) vtable address -- +// CHECK-31-NEXT: 4 | [unused] void Test24::A::f() +// CHECK-31-NEXT: 5 | vcall_offset (0) +// CHECK-31-NEXT: 6 | offset_to_top (8) +// CHECK-31-NEXT: 7 | Test24::C RTTI +// CHECK-31-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-31-NEXT: 8 | void Test24::A::f() struct D : B, C { virtual void f(); }; @@ -1047,44 +1089,44 @@ struct V { struct A : virtual V { }; struct B : virtual V { }; -// CHECK: Vtable for 'Test25::C' (11 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test25::C RTTI -// CHECK-NEXT: -- (Test25::A, 0) vtable address -- -// CHECK-NEXT: -- (Test25::C, 0) vtable address -- -// CHECK-NEXT: -- (Test25::V, 0) vtable address -- -// CHECK-NEXT: 4 | void Test25::V::f() -// CHECK-NEXT: 5 | void Test25::C::g() -// CHECK-NEXT: 6 | vbase_offset (-8) -// CHECK-NEXT: 7 | vcall_offset (-8) -// CHECK-NEXT: 8 | offset_to_top (-8) -// CHECK-NEXT: 9 | Test25::C RTTI -// CHECK-NEXT: -- (Test25::B, 8) vtable address -- -// CHECK-NEXT: 10 | [unused] void Test25::V::f() - -// CHECK: Construction vtable for ('Test25::A', 0) in 'Test25::C' (5 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test25::A RTTI -// CHECK-NEXT: -- (Test25::A, 0) vtable address -- -// CHECK-NEXT: -- (Test25::V, 0) vtable address -- -// CHECK-NEXT: 4 | void Test25::V::f() - -// CHECK: Construction vtable for ('Test25::B', 8) in 'Test25::C' (9 entries). -// CHECK-NEXT: 0 | vbase_offset (-8) -// CHECK-NEXT: 1 | vcall_offset (-8) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test25::B RTTI -// CHECK-NEXT: -- (Test25::B, 8) vtable address -- -// CHECK-NEXT: 4 | [unused] void Test25::V::f() -// CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (8) -// CHECK-NEXT: 7 | Test25::B RTTI -// CHECK-NEXT: -- (Test25::V, 0) vtable address -- -// CHECK-NEXT: 8 | void Test25::V::f() +// CHECK-32: Vtable for 'Test25::C' (11 entries). +// CHECK-32-NEXT: 0 | vbase_offset (0) +// CHECK-32-NEXT: 1 | vcall_offset (0) +// CHECK-32-NEXT: 2 | offset_to_top (0) +// CHECK-32-NEXT: 3 | Test25::C RTTI +// CHECK-32-NEXT: -- (Test25::A, 0) vtable address -- +// CHECK-32-NEXT: -- (Test25::C, 0) vtable address -- +// CHECK-32-NEXT: -- (Test25::V, 0) vtable address -- +// CHECK-32-NEXT: 4 | void Test25::V::f() +// CHECK-32-NEXT: 5 | void Test25::C::g() +// CHECK-32-NEXT: 6 | vbase_offset (-8) +// CHECK-32-NEXT: 7 | vcall_offset (-8) +// CHECK-32-NEXT: 8 | offset_to_top (-8) +// CHECK-32-NEXT: 9 | Test25::C RTTI +// CHECK-32-NEXT: -- (Test25::B, 8) vtable address -- +// CHECK-32-NEXT: 10 | [unused] void Test25::V::f() + +// CHECK-32: Construction vtable for ('Test25::A', 0) in 'Test25::C' (5 entries). +// CHECK-32-NEXT: 0 | vbase_offset (0) +// CHECK-32-NEXT: 1 | vcall_offset (0) +// CHECK-32-NEXT: 2 | offset_to_top (0) +// CHECK-32-NEXT: 3 | Test25::A RTTI +// CHECK-32-NEXT: -- (Test25::A, 0) vtable address -- +// CHECK-32-NEXT: -- (Test25::V, 0) vtable address -- +// CHECK-32-NEXT: 4 | void Test25::V::f() + +// CHECK-32: Construction vtable for ('Test25::B', 8) in 'Test25::C' (9 entries). +// CHECK-32-NEXT: 0 | vbase_offset (-8) +// CHECK-32-NEXT: 1 | vcall_offset (-8) +// CHECK-32-NEXT: 2 | offset_to_top (0) +// CHECK-32-NEXT: 3 | Test25::B RTTI +// CHECK-32-NEXT: -- (Test25::B, 8) vtable address -- +// CHECK-32-NEXT: 4 | [unused] void Test25::V::f() +// CHECK-32-NEXT: 5 | vcall_offset (0) +// CHECK-32-NEXT: 6 | offset_to_top (8) +// CHECK-32-NEXT: 7 | Test25::B RTTI +// CHECK-32-NEXT: -- (Test25::V, 0) vtable address -- +// CHECK-32-NEXT: 8 | void Test25::V::f() struct C : A, virtual V, B { virtual void g(); }; @@ -1109,37 +1151,37 @@ struct C : virtual A { virtual void b(); }; -// CHECK: Vtable for 'Test26::D' (15 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | vbase_offset (0) -// CHECK-NEXT: 3 | vcall_offset (0) -// CHECK-NEXT: 4 | offset_to_top (0) -// CHECK-NEXT: 5 | Test26::D RTTI -// CHECK-NEXT: -- (Test26::B, 0) vtable address -- -// CHECK-NEXT: -- (Test26::D, 0) vtable address -- -// CHECK-NEXT: 6 | void Test26::B::c() -// CHECK-NEXT: 7 | void Test26::D::d() -// CHECK-NEXT: 8 | vcall_offset (0) -// CHECK-NEXT: 9 | vbase_offset (0) -// CHECK-NEXT: 10 | vcall_offset (0) -// CHECK-NEXT: 11 | offset_to_top (-8) -// CHECK-NEXT: 12 | Test26::D RTTI -// CHECK-NEXT: -- (Test26::A, 8) vtable address -- -// CHECK-NEXT: -- (Test26::C, 8) vtable address -- -// CHECK-NEXT: 13 | void Test26::A::a() -// CHECK-NEXT: 14 | void Test26::C::b() - -// CHECK: Construction vtable for ('Test26::C', 8) in 'Test26::D' (7 entries). -// CHECK-NEXT: 0 | vcall_offset (0) -// CHECK-NEXT: 1 | vbase_offset (0) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test26::C RTTI -// CHECK-NEXT: -- (Test26::A, 8) vtable address -- -// CHECK-NEXT: -- (Test26::C, 8) vtable address -- -// CHECK-NEXT: 5 | void Test26::A::a() -// CHECK-NEXT: 6 | void Test26::C::b() +// CHECK-33: Vtable for 'Test26::D' (15 entries). +// CHECK-33-NEXT: 0 | vbase_offset (8) +// CHECK-33-NEXT: 1 | vbase_offset (8) +// CHECK-33-NEXT: 2 | vbase_offset (0) +// CHECK-33-NEXT: 3 | vcall_offset (0) +// CHECK-33-NEXT: 4 | offset_to_top (0) +// CHECK-33-NEXT: 5 | Test26::D RTTI +// CHECK-33-NEXT: -- (Test26::B, 0) vtable address -- +// CHECK-33-NEXT: -- (Test26::D, 0) vtable address -- +// CHECK-33-NEXT: 6 | void Test26::B::c() +// CHECK-33-NEXT: 7 | void Test26::D::d() +// CHECK-33-NEXT: 8 | vcall_offset (0) +// CHECK-33-NEXT: 9 | vbase_offset (0) +// CHECK-33-NEXT: 10 | vcall_offset (0) +// CHECK-33-NEXT: 11 | offset_to_top (-8) +// CHECK-33-NEXT: 12 | Test26::D RTTI +// CHECK-33-NEXT: -- (Test26::A, 8) vtable address -- +// CHECK-33-NEXT: -- (Test26::C, 8) vtable address -- +// CHECK-33-NEXT: 13 | void Test26::A::a() +// CHECK-33-NEXT: 14 | void Test26::C::b() + +// CHECK-33: Construction vtable for ('Test26::C', 8) in 'Test26::D' (7 entries). +// CHECK-33-NEXT: 0 | vcall_offset (0) +// CHECK-33-NEXT: 1 | vbase_offset (0) +// CHECK-33-NEXT: 2 | vcall_offset (0) +// CHECK-33-NEXT: 3 | offset_to_top (0) +// CHECK-33-NEXT: 4 | Test26::C RTTI +// CHECK-33-NEXT: -- (Test26::A, 8) vtable address -- +// CHECK-33-NEXT: -- (Test26::C, 8) vtable address -- +// CHECK-33-NEXT: 5 | void Test26::A::a() +// CHECK-33-NEXT: 6 | void Test26::C::b() class D : virtual B, virtual C { virtual void d(); }; @@ -1168,39 +1210,39 @@ struct D : A, virtual B, C { virtual void d(); }; -// CHECK: Vtable for 'Test27::E' (13 entries). -// CHECK-NEXT: 0 | vbase_offset (16) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test27::E RTTI -// CHECK-NEXT: -- (Test27::A, 0) vtable address -- -// CHECK-NEXT: -- (Test27::D, 0) vtable address -- -// CHECK-NEXT: -- (Test27::E, 0) vtable address -- -// CHECK-NEXT: 3 | void Test27::A::a() -// CHECK-NEXT: 4 | void Test27::D::d() -// CHECK-NEXT: 5 | void Test27::E::e() -// CHECK-NEXT: 6 | offset_to_top (-8) -// CHECK-NEXT: 7 | Test27::E RTTI -// CHECK-NEXT: -- (Test27::C, 8) vtable address -- -// CHECK-NEXT: 8 | void Test27::C::c() -// CHECK-NEXT: 9 | vcall_offset (0) -// CHECK-NEXT: 10 | offset_to_top (-16) -// CHECK-NEXT: 11 | Test27::E RTTI -// CHECK-NEXT: -- (Test27::B, 16) vtable address -- -// CHECK-NEXT: 12 | void Test27::B::b() - -// CHECK: Construction vtable for ('Test27::D', 0) in 'Test27::E' (9 entries). -// CHECK-NEXT: 0 | vbase_offset (16) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test27::D RTTI -// CHECK-NEXT: -- (Test27::A, 0) vtable address -- -// CHECK-NEXT: -- (Test27::D, 0) vtable address -- -// CHECK-NEXT: 3 | void Test27::A::a() -// CHECK-NEXT: 4 | void Test27::D::d() -// CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (-16) -// CHECK-NEXT: 7 | Test27::D RTTI -// CHECK-NEXT: -- (Test27::B, 16) vtable address -- -// CHECK-NEXT: 8 | void Test27::B::b() +// CHECK-34: Vtable for 'Test27::E' (13 entries). +// CHECK-34-NEXT: 0 | vbase_offset (16) +// CHECK-34-NEXT: 1 | offset_to_top (0) +// CHECK-34-NEXT: 2 | Test27::E RTTI +// CHECK-34-NEXT: -- (Test27::A, 0) vtable address -- +// CHECK-34-NEXT: -- (Test27::D, 0) vtable address -- +// CHECK-34-NEXT: -- (Test27::E, 0) vtable address -- +// CHECK-34-NEXT: 3 | void Test27::A::a() +// CHECK-34-NEXT: 4 | void Test27::D::d() +// CHECK-34-NEXT: 5 | void Test27::E::e() +// CHECK-34-NEXT: 6 | offset_to_top (-8) +// CHECK-34-NEXT: 7 | Test27::E RTTI +// CHECK-34-NEXT: -- (Test27::C, 8) vtable address -- +// CHECK-34-NEXT: 8 | void Test27::C::c() +// CHECK-34-NEXT: 9 | vcall_offset (0) +// CHECK-34-NEXT: 10 | offset_to_top (-16) +// CHECK-34-NEXT: 11 | Test27::E RTTI +// CHECK-34-NEXT: -- (Test27::B, 16) vtable address -- +// CHECK-34-NEXT: 12 | void Test27::B::b() + +// CHECK-34: Construction vtable for ('Test27::D', 0) in 'Test27::E' (9 entries). +// CHECK-34-NEXT: 0 | vbase_offset (16) +// CHECK-34-NEXT: 1 | offset_to_top (0) +// CHECK-34-NEXT: 2 | Test27::D RTTI +// CHECK-34-NEXT: -- (Test27::A, 0) vtable address -- +// CHECK-34-NEXT: -- (Test27::D, 0) vtable address -- +// CHECK-34-NEXT: 3 | void Test27::A::a() +// CHECK-34-NEXT: 4 | void Test27::D::d() +// CHECK-34-NEXT: 5 | vcall_offset (0) +// CHECK-34-NEXT: 6 | offset_to_top (-16) +// CHECK-34-NEXT: 7 | Test27::D RTTI +// CHECK-34-NEXT: -- (Test27::B, 16) vtable address -- +// CHECK-34-NEXT: 8 | void Test27::B::b() struct E : D { virtual void e(); }; @@ -1228,45 +1270,45 @@ struct C : A, B { struct D : virtual C { }; -// CHECK: Vtable for 'Test28::E' (14 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test28::E RTTI -// CHECK-NEXT: -- (Test28::D, 0) vtable address -- -// CHECK-NEXT: -- (Test28::E, 0) vtable address -- -// CHECK-NEXT: 3 | void Test28::E::e() -// CHECK-NEXT: 4 | vcall_offset (8) -// CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | vcall_offset (0) -// CHECK-NEXT: 7 | offset_to_top (-8) -// CHECK-NEXT: 8 | Test28::E RTTI -// CHECK-NEXT: -- (Test28::A, 8) vtable address -- -// CHECK-NEXT: -- (Test28::C, 8) vtable address -- -// CHECK-NEXT: 9 | void Test28::A::a() -// CHECK-NEXT: 10 | void Test28::C::c() -// CHECK-NEXT: 11 | offset_to_top (-16) -// CHECK-NEXT: 12 | Test28::E RTTI -// CHECK-NEXT: -- (Test28::B, 16) vtable address -- -// CHECK-NEXT: 13 | void Test28::B::b() - -// CHECK: Construction vtable for ('Test28::D', 0) in 'Test28::E' (13 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | offset_to_top (0) -// CHECK-NEXT: 2 | Test28::D RTTI -// CHECK-NEXT: -- (Test28::D, 0) vtable address -- -// CHECK-NEXT: 3 | vcall_offset (8) -// CHECK-NEXT: 4 | vcall_offset (0) -// CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (-8) -// CHECK-NEXT: 7 | Test28::D RTTI -// CHECK-NEXT: -- (Test28::A, 8) vtable address -- -// CHECK-NEXT: -- (Test28::C, 8) vtable address -- -// CHECK-NEXT: 8 | void Test28::A::a() -// CHECK-NEXT: 9 | void Test28::C::c() -// CHECK-NEXT: 10 | offset_to_top (-16) -// CHECK-NEXT: 11 | Test28::D RTTI -// CHECK-NEXT: -- (Test28::B, 16) vtable address -- -// CHECK-NEXT: 12 | void Test28::B::b() +// CHECK-35: Vtable for 'Test28::E' (14 entries). +// CHECK-35-NEXT: 0 | vbase_offset (8) +// CHECK-35-NEXT: 1 | offset_to_top (0) +// CHECK-35-NEXT: 2 | Test28::E RTTI +// CHECK-35-NEXT: -- (Test28::D, 0) vtable address -- +// CHECK-35-NEXT: -- (Test28::E, 0) vtable address -- +// CHECK-35-NEXT: 3 | void Test28::E::e() +// CHECK-35-NEXT: 4 | vcall_offset (8) +// CHECK-35-NEXT: 5 | vcall_offset (0) +// CHECK-35-NEXT: 6 | vcall_offset (0) +// CHECK-35-NEXT: 7 | offset_to_top (-8) +// CHECK-35-NEXT: 8 | Test28::E RTTI +// CHECK-35-NEXT: -- (Test28::A, 8) vtable address -- +// CHECK-35-NEXT: -- (Test28::C, 8) vtable address -- +// CHECK-35-NEXT: 9 | void Test28::A::a() +// CHECK-35-NEXT: 10 | void Test28::C::c() +// CHECK-35-NEXT: 11 | offset_to_top (-16) +// CHECK-35-NEXT: 12 | Test28::E RTTI +// CHECK-35-NEXT: -- (Test28::B, 16) vtable address -- +// CHECK-35-NEXT: 13 | void Test28::B::b() + +// CHECK-35: Construction vtable for ('Test28::D', 0) in 'Test28::E' (13 entries). +// CHECK-35-NEXT: 0 | vbase_offset (8) +// CHECK-35-NEXT: 1 | offset_to_top (0) +// CHECK-35-NEXT: 2 | Test28::D RTTI +// CHECK-35-NEXT: -- (Test28::D, 0) vtable address -- +// CHECK-35-NEXT: 3 | vcall_offset (8) +// CHECK-35-NEXT: 4 | vcall_offset (0) +// CHECK-35-NEXT: 5 | vcall_offset (0) +// CHECK-35-NEXT: 6 | offset_to_top (-8) +// CHECK-35-NEXT: 7 | Test28::D RTTI +// CHECK-35-NEXT: -- (Test28::A, 8) vtable address -- +// CHECK-35-NEXT: -- (Test28::C, 8) vtable address -- +// CHECK-35-NEXT: 8 | void Test28::A::a() +// CHECK-35-NEXT: 9 | void Test28::C::c() +// CHECK-35-NEXT: 10 | offset_to_top (-16) +// CHECK-35-NEXT: 11 | Test28::D RTTI +// CHECK-35-NEXT: -- (Test28::B, 16) vtable address -- +// CHECK-35-NEXT: 12 | void Test28::B::b() struct E : D { virtual void e(); }; @@ -1286,17 +1328,17 @@ struct A { virtual V1 *f(); }; -// CHECK: Vtable for 'Test29::B' (6 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vcall_offset (0) -// CHECK-NEXT: 2 | offset_to_top (0) -// CHECK-NEXT: 3 | Test29::B RTTI -// CHECK-NEXT: -- (Test29::A, 0) vtable address -- -// CHECK-NEXT: -- (Test29::B, 0) vtable address -- -// CHECK-NEXT: 4 | Test29::V2 *Test29::B::f() -// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] -// CHECK-NEXT: 5 | Test29::V2 *Test29::B::f() +// CHECK-36: Vtable for 'Test29::B' (6 entries). +// CHECK-36-NEXT: 0 | vbase_offset (0) +// CHECK-36-NEXT: 1 | vcall_offset (0) +// CHECK-36-NEXT: 2 | offset_to_top (0) +// CHECK-36-NEXT: 3 | Test29::B RTTI +// CHECK-36-NEXT: -- (Test29::A, 0) vtable address -- +// CHECK-36-NEXT: -- (Test29::B, 0) vtable address -- +// CHECK-36-NEXT: 4 | Test29::V2 *Test29::B::f() +// CHECK-36-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] +// CHECK-36-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-36-NEXT: 5 | Test29::V2 *Test29::B::f() struct B : virtual A { virtual V2 *f(); }; @@ -1342,22 +1384,22 @@ struct C : A, virtual B { virtual void f(); }; -// CHECK: Vtable for 'Test31::D' (11 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test31::D RTTI -// CHECK-NEXT: -- (Test31::B, 0) vtable address -- -// CHECK-NEXT: -- (Test31::D, 0) vtable address -- -// CHECK-NEXT: 5 | void Test31::D::f() -// CHECK-NEXT: 6 | vbase_offset (-8) -// CHECK-NEXT: 7 | vcall_offset (-8) -// CHECK-NEXT: 8 | offset_to_top (-8) -// CHECK-NEXT: 9 | Test31::D RTTI -// CHECK-NEXT: -- (Test31::C, 8) vtable address -- -// CHECK-NEXT: 10 | void Test31::D::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-37: Vtable for 'Test31::D' (11 entries). +// CHECK-37-NEXT: 0 | vbase_offset (0) +// CHECK-37-NEXT: 1 | vbase_offset (8) +// CHECK-37-NEXT: 2 | vcall_offset (0) +// CHECK-37-NEXT: 3 | offset_to_top (0) +// CHECK-37-NEXT: 4 | Test31::D RTTI +// CHECK-37-NEXT: -- (Test31::B, 0) vtable address -- +// CHECK-37-NEXT: -- (Test31::D, 0) vtable address -- +// CHECK-37-NEXT: 5 | void Test31::D::f() +// CHECK-37-NEXT: 6 | vbase_offset (-8) +// CHECK-37-NEXT: 7 | vcall_offset (-8) +// CHECK-37-NEXT: 8 | offset_to_top (-8) +// CHECK-37-NEXT: 9 | Test31::D RTTI +// CHECK-37-NEXT: -- (Test31::C, 8) vtable address -- +// CHECK-37-NEXT: 10 | void Test31::D::f() +// CHECK-37-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] struct D : virtual C { virtual void f(); }; @@ -1377,10 +1419,10 @@ struct B : virtual A { }; struct C : A, virtual B { }; struct D : virtual B { }; -// CHECK: Virtual base offset offsets for 'Test32::E' (3 entries). -// CHECK-NEXT: Test32::A | -32 -// CHECK-NEXT: Test32::B | -24 -// CHECK-NEXT: Test32::D | -40 +// CHECK-38: Virtual base offset offsets for 'Test32::E' (3 entries). +// CHECK-38-NEXT: Test32::A | -32 +// CHECK-38-NEXT: Test32::B | -24 +// CHECK-38-NEXT: Test32::D | -40 struct E : C, virtual D { virtual void f(); }; @@ -1410,45 +1452,45 @@ struct E : A, D { virtual void e(); }; -// CHECK: Vtable for 'Test33::F' (30 entries). -// CHECK-NEXT: 0 | vbase_offset (24) -// CHECK-NEXT: 1 | vbase_offset (16) -// CHECK-NEXT: 2 | vbase_offset (16) -// CHECK-NEXT: 3 | vbase_offset (8) -// CHECK-NEXT: 4 | offset_to_top (0) -// CHECK-NEXT: 5 | Test33::F RTTI -// CHECK-NEXT: -- (Test33::A, 0) vtable address -- -// CHECK-NEXT: -- (Test33::F, 0) vtable address -- -// CHECK-NEXT: 6 | void Test33::A::a() -// CHECK-NEXT: 7 | void Test33::F::f() -// CHECK-NEXT: 8 | vcall_offset (0) -// CHECK-NEXT: 9 | vcall_offset (0) -// CHECK-NEXT: 10 | vbase_offset (16) -// CHECK-NEXT: 11 | vbase_offset (8) -// CHECK-NEXT: 12 | vbase_offset (8) -// CHECK-NEXT: 13 | offset_to_top (-8) -// CHECK-NEXT: 14 | Test33::F RTTI -// CHECK-NEXT: -- (Test33::A, 8) vtable address -- -// CHECK-NEXT: -- (Test33::E, 8) vtable address -- -// CHECK-NEXT: 15 | void Test33::A::a() -// CHECK-NEXT: 16 | void Test33::E::e() -// CHECK-NEXT: 17 | vbase_offset (0) -// CHECK-NEXT: 18 | vcall_offset (0) -// CHECK-NEXT: 19 | vbase_offset (8) -// CHECK-NEXT: 20 | vbase_offset (0) -// CHECK-NEXT: 21 | vcall_offset (0) -// CHECK-NEXT: 22 | offset_to_top (-16) -// CHECK-NEXT: 23 | Test33::F RTTI -// CHECK-NEXT: -- (Test33::A, 16) vtable address -- -// CHECK-NEXT: -- (Test33::C, 16) vtable address -- -// CHECK-NEXT: -- (Test33::D, 16) vtable address -- -// CHECK-NEXT: 24 | void Test33::A::a() -// CHECK-NEXT: 25 | void Test33::C::c() -// CHECK-NEXT: 26 | vcall_offset (0) -// CHECK-NEXT: 27 | offset_to_top (-24) -// CHECK-NEXT: 28 | Test33::F RTTI -// CHECK-NEXT: -- (Test33::B, 24) vtable address -- -// CHECK-NEXT: 29 | void Test33::B::b() +// CHECK-39: Vtable for 'Test33::F' (30 entries). +// CHECK-39-NEXT: 0 | vbase_offset (24) +// CHECK-39-NEXT: 1 | vbase_offset (16) +// CHECK-39-NEXT: 2 | vbase_offset (16) +// CHECK-39-NEXT: 3 | vbase_offset (8) +// CHECK-39-NEXT: 4 | offset_to_top (0) +// CHECK-39-NEXT: 5 | Test33::F RTTI +// CHECK-39-NEXT: -- (Test33::A, 0) vtable address -- +// CHECK-39-NEXT: -- (Test33::F, 0) vtable address -- +// CHECK-39-NEXT: 6 | void Test33::A::a() +// CHECK-39-NEXT: 7 | void Test33::F::f() +// CHECK-39-NEXT: 8 | vcall_offset (0) +// CHECK-39-NEXT: 9 | vcall_offset (0) +// CHECK-39-NEXT: 10 | vbase_offset (16) +// CHECK-39-NEXT: 11 | vbase_offset (8) +// CHECK-39-NEXT: 12 | vbase_offset (8) +// CHECK-39-NEXT: 13 | offset_to_top (-8) +// CHECK-39-NEXT: 14 | Test33::F RTTI +// CHECK-39-NEXT: -- (Test33::A, 8) vtable address -- +// CHECK-39-NEXT: -- (Test33::E, 8) vtable address -- +// CHECK-39-NEXT: 15 | void Test33::A::a() +// CHECK-39-NEXT: 16 | void Test33::E::e() +// CHECK-39-NEXT: 17 | vbase_offset (0) +// CHECK-39-NEXT: 18 | vcall_offset (0) +// CHECK-39-NEXT: 19 | vbase_offset (8) +// CHECK-39-NEXT: 20 | vbase_offset (0) +// CHECK-39-NEXT: 21 | vcall_offset (0) +// CHECK-39-NEXT: 22 | offset_to_top (-16) +// CHECK-39-NEXT: 23 | Test33::F RTTI +// CHECK-39-NEXT: -- (Test33::A, 16) vtable address -- +// CHECK-39-NEXT: -- (Test33::C, 16) vtable address -- +// CHECK-39-NEXT: -- (Test33::D, 16) vtable address -- +// CHECK-39-NEXT: 24 | void Test33::A::a() +// CHECK-39-NEXT: 25 | void Test33::C::c() +// CHECK-39-NEXT: 26 | vcall_offset (0) +// CHECK-39-NEXT: 27 | offset_to_top (-24) +// CHECK-39-NEXT: 28 | Test33::F RTTI +// CHECK-39-NEXT: -- (Test33::B, 24) vtable address -- +// CHECK-39-NEXT: 29 | void Test33::B::b() struct F : virtual E, A { virtual void f(); }; @@ -1475,36 +1517,36 @@ struct E : virtual D { virtual void e(); }; -// CHECK: Construction vtable for ('Test34::E', 0) in 'Test34::F' (22 entries). -// CHECK-NEXT: 0 | vbase_offset (0) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test34::E RTTI -// CHECK-NEXT: -- (Test34::A, 0) vtable address -- -// CHECK-NEXT: -- (Test34::E, 0) vtable address -- -// CHECK-NEXT: 5 | void Test34::A::a() -// CHECK-NEXT: 6 | void Test34::E::e() -// CHECK-NEXT: 7 | vcall_offset (8) -// CHECK-NEXT: 8 | vcall_offset (0) -// CHECK-NEXT: 9 | vbase_offset (-8) -// CHECK-NEXT: 10 | offset_to_top (-8) -// CHECK-NEXT: 11 | Test34::E RTTI -// CHECK-NEXT: -- (Test34::A, 8) vtable address -- -// CHECK-NEXT: -- (Test34::D, 8) vtable address -- -// CHECK-NEXT: 12 | void Test34::A::a() -// CHECK-NEXT: 13 | vbase_offset (-16) -// CHECK-NEXT: 14 | vcall_offset (-16) -// CHECK-NEXT: 15 | offset_to_top (-16) -// CHECK-NEXT: 16 | Test34::E RTTI -// CHECK-NEXT: -- (Test34::B, 16) vtable address -- -// CHECK-NEXT: -- (Test34::C, 16) vtable address -- -// CHECK-NEXT: 17 | [unused] void Test34::A::a() -// CHECK-NEXT: 18 | void Test34::C::c() -// CHECK-NEXT: 19 | offset_to_top (-24) -// CHECK-NEXT: 20 | Test34::E RTTI -// CHECK-NEXT: -- (Test34::A, 24) vtable address -- -// CHECK-NEXT: 21 | void Test34::A::a() +// CHECK-40: Construction vtable for ('Test34::E', 0) in 'Test34::F' (22 entries). +// CHECK-40-NEXT: 0 | vbase_offset (0) +// CHECK-40-NEXT: 1 | vbase_offset (8) +// CHECK-40-NEXT: 2 | vcall_offset (0) +// CHECK-40-NEXT: 3 | offset_to_top (0) +// CHECK-40-NEXT: 4 | Test34::E RTTI +// CHECK-40-NEXT: -- (Test34::A, 0) vtable address -- +// CHECK-40-NEXT: -- (Test34::E, 0) vtable address -- +// CHECK-40-NEXT: 5 | void Test34::A::a() +// CHECK-40-NEXT: 6 | void Test34::E::e() +// CHECK-40-NEXT: 7 | vcall_offset (8) +// CHECK-40-NEXT: 8 | vcall_offset (0) +// CHECK-40-NEXT: 9 | vbase_offset (-8) +// CHECK-40-NEXT: 10 | offset_to_top (-8) +// CHECK-40-NEXT: 11 | Test34::E RTTI +// CHECK-40-NEXT: -- (Test34::A, 8) vtable address -- +// CHECK-40-NEXT: -- (Test34::D, 8) vtable address -- +// CHECK-40-NEXT: 12 | void Test34::A::a() +// CHECK-40-NEXT: 13 | vbase_offset (-16) +// CHECK-40-NEXT: 14 | vcall_offset (-16) +// CHECK-40-NEXT: 15 | offset_to_top (-16) +// CHECK-40-NEXT: 16 | Test34::E RTTI +// CHECK-40-NEXT: -- (Test34::B, 16) vtable address -- +// CHECK-40-NEXT: -- (Test34::C, 16) vtable address -- +// CHECK-40-NEXT: 17 | [unused] void Test34::A::a() +// CHECK-40-NEXT: 18 | void Test34::C::c() +// CHECK-40-NEXT: 19 | offset_to_top (-24) +// CHECK-40-NEXT: 20 | Test34::E RTTI +// CHECK-40-NEXT: -- (Test34::A, 24) vtable address -- +// CHECK-40-NEXT: 21 | void Test34::A::a() struct F : E { virtual void f(); }; @@ -1543,55 +1585,55 @@ struct E : D { struct F : virtual D { }; struct G : virtual E { }; -// CHECK: Vtable for 'Test35::H' (32 entries). -// CHECK-NEXT: 0 | vbase_offset (32) -// CHECK-NEXT: 1 | vbase_offset (0) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | vcall_offset (0) -// CHECK-NEXT: 4 | vbase_offset (16) -// CHECK-NEXT: 5 | vbase_offset (8) -// CHECK-NEXT: 6 | offset_to_top (0) -// CHECK-NEXT: 7 | Test35::H RTTI -// CHECK-NEXT: -- (Test35::C, 0) vtable address -- -// CHECK-NEXT: -- (Test35::D, 0) vtable address -- -// CHECK-NEXT: -- (Test35::F, 0) vtable address -- -// CHECK-NEXT: -- (Test35::H, 0) vtable address -- -// CHECK-NEXT: 8 | void Test35::C::c() -// CHECK-NEXT: 9 | void Test35::D::d() -// CHECK-NEXT: 10 | void Test35::H::h() -// CHECK-NEXT: 11 | vbase_offset (0) -// CHECK-NEXT: 12 | vbase_offset (24) -// CHECK-NEXT: 13 | vcall_offset (0) -// CHECK-NEXT: 14 | vbase_offset (8) -// CHECK-NEXT: 15 | offset_to_top (-8) -// CHECK-NEXT: 16 | Test35::H RTTI -// CHECK-NEXT: -- (Test35::B, 8) vtable address -- -// CHECK-NEXT: -- (Test35::G, 8) vtable address -- -// CHECK-NEXT: 17 | void Test35::B::b() -// CHECK-NEXT: 18 | vcall_offset (0) -// CHECK-NEXT: 19 | offset_to_top (-16) -// CHECK-NEXT: 20 | Test35::H RTTI -// CHECK-NEXT: -- (Test35::A, 16) vtable address -- -// CHECK-NEXT: 21 | void Test35::A::a() -// CHECK-NEXT: 22 | vcall_offset (0) -// CHECK-NEXT: 23 | vcall_offset (0) -// CHECK-NEXT: 24 | vcall_offset (0) -// CHECK-NEXT: 25 | vbase_offset (-16) -// CHECK-NEXT: 26 | vbase_offset (-24) -// CHECK-NEXT: 27 | offset_to_top (-32) -// CHECK-NEXT: 28 | Test35::H RTTI -// CHECK-NEXT: -- (Test35::C, 32) vtable address -- -// CHECK-NEXT: -- (Test35::D, 32) vtable address -- -// CHECK-NEXT: -- (Test35::E, 32) vtable address -- -// CHECK-NEXT: 29 | void Test35::C::c() -// CHECK-NEXT: 30 | void Test35::D::d() -// CHECK-NEXT: 31 | void Test35::E::e() - -// CHECK: Virtual base offset offsets for 'Test35::H' (4 entries). -// CHECK-NEXT: Test35::A | -32 -// CHECK-NEXT: Test35::B | -24 -// CHECK-NEXT: Test35::D | -56 -// CHECK-NEXT: Test35::E | -64 +// CHECK-41: Vtable for 'Test35::H' (32 entries). +// CHECK-41-NEXT: 0 | vbase_offset (32) +// CHECK-41-NEXT: 1 | vbase_offset (0) +// CHECK-41-NEXT: 2 | vcall_offset (0) +// CHECK-41-NEXT: 3 | vcall_offset (0) +// CHECK-41-NEXT: 4 | vbase_offset (16) +// CHECK-41-NEXT: 5 | vbase_offset (8) +// CHECK-41-NEXT: 6 | offset_to_top (0) +// CHECK-41-NEXT: 7 | Test35::H RTTI +// CHECK-41-NEXT: -- (Test35::C, 0) vtable address -- +// CHECK-41-NEXT: -- (Test35::D, 0) vtable address -- +// CHECK-41-NEXT: -- (Test35::F, 0) vtable address -- +// CHECK-41-NEXT: -- (Test35::H, 0) vtable address -- +// CHECK-41-NEXT: 8 | void Test35::C::c() +// CHECK-41-NEXT: 9 | void Test35::D::d() +// CHECK-41-NEXT: 10 | void Test35::H::h() +// CHECK-41-NEXT: 11 | vbase_offset (0) +// CHECK-41-NEXT: 12 | vbase_offset (24) +// CHECK-41-NEXT: 13 | vcall_offset (0) +// CHECK-41-NEXT: 14 | vbase_offset (8) +// CHECK-41-NEXT: 15 | offset_to_top (-8) +// CHECK-41-NEXT: 16 | Test35::H RTTI +// CHECK-41-NEXT: -- (Test35::B, 8) vtable address -- +// CHECK-41-NEXT: -- (Test35::G, 8) vtable address -- +// CHECK-41-NEXT: 17 | void Test35::B::b() +// CHECK-41-NEXT: 18 | vcall_offset (0) +// CHECK-41-NEXT: 19 | offset_to_top (-16) +// CHECK-41-NEXT: 20 | Test35::H RTTI +// CHECK-41-NEXT: -- (Test35::A, 16) vtable address -- +// CHECK-41-NEXT: 21 | void Test35::A::a() +// CHECK-41-NEXT: 22 | vcall_offset (0) +// CHECK-41-NEXT: 23 | vcall_offset (0) +// CHECK-41-NEXT: 24 | vcall_offset (0) +// CHECK-41-NEXT: 25 | vbase_offset (-16) +// CHECK-41-NEXT: 26 | vbase_offset (-24) +// CHECK-41-NEXT: 27 | offset_to_top (-32) +// CHECK-41-NEXT: 28 | Test35::H RTTI +// CHECK-41-NEXT: -- (Test35::C, 32) vtable address -- +// CHECK-41-NEXT: -- (Test35::D, 32) vtable address -- +// CHECK-41-NEXT: -- (Test35::E, 32) vtable address -- +// CHECK-41-NEXT: 29 | void Test35::C::c() +// CHECK-41-NEXT: 30 | void Test35::D::d() +// CHECK-41-NEXT: 31 | void Test35::E::e() + +// CHECK-41: Virtual base offset offsets for 'Test35::H' (4 entries). +// CHECK-41-NEXT: Test35::A | -32 +// CHECK-41-NEXT: Test35::B | -24 +// CHECK-41-NEXT: Test35::D | -56 +// CHECK-41-NEXT: Test35::E | -64 struct H : F, G { virtual void h(); }; @@ -1613,24 +1655,24 @@ struct C : virtual A { virtual void f(); }; -// CHECK: Vtable for 'Test36::D' (12 entries). -// CHECK-NEXT: 0 | vbase_offset (8) -// CHECK-NEXT: 1 | vbase_offset (8) -// CHECK-NEXT: 2 | vcall_offset (0) -// CHECK-NEXT: 3 | offset_to_top (0) -// CHECK-NEXT: 4 | Test36::D RTTI -// CHECK-NEXT: -- (Test36::C, 0) vtable address -- -// CHECK-NEXT: -- (Test36::D, 0) vtable address -- -// CHECK-NEXT: 5 | void Test36::C::f() -// CHECK-NEXT: 6 | void Test36::D::g() -// CHECK-NEXT: 7 | vbase_offset (0) -// CHECK-NEXT: 8 | vcall_offset (-8) -// CHECK-NEXT: 9 | offset_to_top (-8) -// CHECK-NEXT: 10 | Test36::D RTTI -// CHECK-NEXT: -- (Test36::A, 8) vtable address -- -// CHECK-NEXT: -- (Test36::B, 8) vtable address -- -// CHECK-NEXT: 11 | void Test36::C::f() -// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-42: Vtable for 'Test36::D' (12 entries). +// CHECK-42-NEXT: 0 | vbase_offset (8) +// CHECK-42-NEXT: 1 | vbase_offset (8) +// CHECK-42-NEXT: 2 | vcall_offset (0) +// CHECK-42-NEXT: 3 | offset_to_top (0) +// CHECK-42-NEXT: 4 | Test36::D RTTI +// CHECK-42-NEXT: -- (Test36::C, 0) vtable address -- +// CHECK-42-NEXT: -- (Test36::D, 0) vtable address -- +// CHECK-42-NEXT: 5 | void Test36::C::f() +// CHECK-42-NEXT: 6 | void Test36::D::g() +// CHECK-42-NEXT: 7 | vbase_offset (0) +// CHECK-42-NEXT: 8 | vcall_offset (-8) +// CHECK-42-NEXT: 9 | offset_to_top (-8) +// CHECK-42-NEXT: 10 | Test36::D RTTI +// CHECK-42-NEXT: -- (Test36::A, 8) vtable address -- +// CHECK-42-NEXT: -- (Test36::B, 8) vtable address -- +// CHECK-42-NEXT: 11 | void Test36::C::f() +// CHECK-42-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] struct D : virtual B, C { virtual void g(); }; diff --git a/clang/test/CodeGenCXX/vtable-linkage.cpp b/clang/test/CodeGenCXX/vtable-linkage.cpp index c75efe228dff5f44599c42029311bdb5792a5547..02b1d5c748346a56ea320a652583a6f6c401850d 100644 --- a/clang/test/CodeGenCXX/vtable-linkage.cpp +++ b/clang/test/CodeGenCXX/vtable-linkage.cpp @@ -1,4 +1,16 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t +// RUN: FileCheck --check-prefix=CHECK-1 %s < %t +// RUN: FileCheck --check-prefix=CHECK-2 %s < %t +// RUN: FileCheck --check-prefix=CHECK-3 %s < %t +// RUN: FileCheck --check-prefix=CHECK-4 %s < %t +// RUN: FileCheck --check-prefix=CHECK-5 %s < %t +// RUN: FileCheck --check-prefix=CHECK-6 %s < %t +// RUN: FileCheck --check-prefix=CHECK-7 %s < %t +// RUN: FileCheck --check-prefix=CHECK-8 %s < %t +// RUN: FileCheck --check-prefix=CHECK-9 %s < %t +// RUN: FileCheck --check-prefix=CHECK-10 %s < %t +// RUN: FileCheck --check-prefix=CHECK-11 %s < %t +// RUN: FileCheck --check-prefix=CHECK-12 %s < %t namespace { struct A { @@ -73,7 +85,7 @@ extern template struct F; void use_F(F &fc) { F fi; - (void)fi; + fi.foo(); F fl; (void)fl; fc.foo(); @@ -81,71 +93,71 @@ void use_F(F &fc) { // B has a key function that is not defined in this translation unit so its vtable // has external linkage. -// CHECK: @_ZTV1B = external constant +// CHECK-1: @_ZTV1B = external constant // C has no key function, so its vtable should have weak_odr linkage. -// CHECK: @_ZTV1C = weak_odr constant -// CHECK: @_ZTS1C = weak_odr constant -// CHECK: @_ZTI1C = weak_odr constant +// CHECK-2: @_ZTV1C = weak_odr constant +// CHECK-2: @_ZTS1C = weak_odr constant +// CHECK-2: @_ZTI1C = weak_odr constant // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. -// CHECK: @_ZTV1D = constant -// CHECK: @_ZTS1D = constant -// CHECK: @_ZTI1D = constant +// CHECK-3: @_ZTV1D = constant +// CHECK-3: @_ZTS1D = constant +// CHECK-3: @_ZTI1D = constant // E is an explicit specialization with a key function defined // in this translation unit, so its vtable should have external // linkage. -// CHECK: @_ZTV1EIcE = constant -// CHECK: @_ZTS1EIcE = constant -// CHECK: @_ZTI1EIcE = constant +// CHECK-4: @_ZTV1EIcE = constant +// CHECK-4: @_ZTS1EIcE = constant +// CHECK-4: @_ZTI1EIcE = constant // E is an explicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. -// CHECK: @_ZTV1EIsE = weak_odr constant -// CHECK: @_ZTS1EIsE = weak_odr constant -// CHECK: @_ZTI1EIsE = weak_odr constant +// CHECK-5: @_ZTV1EIsE = weak_odr constant +// CHECK-5: @_ZTS1EIsE = weak_odr constant +// CHECK-5: @_ZTI1EIsE = weak_odr constant // F is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage -// CHECK: @_ZTV1FIsE = weak_odr constant -// CHECK: @_ZTS1FIsE = weak_odr constant -// CHECK: @_ZTI1FIsE = weak_odr constant +// CHECK-6: @_ZTV1FIsE = weak_odr constant +// CHECK-6: @_ZTS1FIsE = weak_odr constant +// CHECK-6: @_ZTI1FIsE = weak_odr constant // E is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. -// CHECK: @_ZTV1EIlE = weak_odr constant -// CHECK: @_ZTS1EIlE = weak_odr constant -// CHECK: @_ZTI1EIlE = weak_odr constant +// CHECK-7: @_ZTV1EIlE = weak_odr constant +// CHECK-7: @_ZTS1EIlE = weak_odr constant +// CHECK-7: @_ZTI1EIlE = weak_odr constant // F is an implicit template instantiation with no key function, // so its vtable should have weak_odr linkage. -// CHECK: @_ZTV1FIlE = weak_odr constant -// CHECK: @_ZTS1FIlE = weak_odr constant -// CHECK: @_ZTI1FIlE = weak_odr constant +// CHECK-8: @_ZTV1FIlE = weak_odr constant +// CHECK-8: @_ZTS1FIlE = weak_odr constant +// CHECK-8: @_ZTI1FIlE = weak_odr constant // F is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. -// CHECK: @_ZTV1FIiE = external constant +// CHECK-9: @_ZTV1FIiE = external constant // E is an explicit template instantiation declaration. It has a // key function that is not instantiated, so we should only reference // its vtable, not define it. -// CHECK: @_ZTV1EIiE = external constant +// CHECK-10: @_ZTV1EIiE = external constant // The anonymous struct for e has no linkage, so the vtable should have // internal linkage. -// CHECK: @"_ZTV3$_0" = internal constant -// CHECK: @"_ZTS3$_0" = internal constant -// CHECK: @"_ZTI3$_0" = internal constant +// CHECK-11: @"_ZTV3$_0" = internal constant +// CHECK-11: @"_ZTS3$_0" = internal constant +// CHECK-11: @"_ZTI3$_0" = internal constant // The A vtable should have internal linkage since it is inside an anonymous // namespace. -// CHECK: @_ZTVN12_GLOBAL__N_11AE = internal constant -// CHECK: @_ZTSN12_GLOBAL__N_11AE = internal constant -// CHECK: @_ZTIN12_GLOBAL__N_11AE = internal constant +// CHECK-12: @_ZTVN12_GLOBAL__N_11AE = internal constant +// CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant +// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant diff --git a/clang/test/SemaCXX/implicit-virtual-member-functions.cpp b/clang/test/SemaCXX/implicit-virtual-member-functions.cpp index cb245011a8735d76f33aa4e4b0423b371586dbc3..f6082e5699ccbb6bd144cf8c31d35ede435571f2 100644 --- a/clang/test/SemaCXX/implicit-virtual-member-functions.cpp +++ b/clang/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -21,9 +21,9 @@ C::C() { } // expected-note {{implicit default destructor for 'C' first require struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'D' first required here}} +}; void f() { - new D; + new D; // expected-note {{implicit default destructor for 'D' first required here}} } diff --git a/clang/test/SemaCXX/virtual-member-functions-key-function.cpp b/clang/test/SemaCXX/virtual-member-functions-key-function.cpp index 97164d93affc78c35ab7d53bc09f89795c8a6f51..09a30b93605ee5952ec4d405d1dd8d3f2e2f20ce 100644 --- a/clang/test/SemaCXX/virtual-member-functions-key-function.cpp +++ b/clang/test/SemaCXX/virtual-member-functions-key-function.cpp @@ -4,17 +4,17 @@ struct A { }; struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} - B() { } + B() { } // expected-note {{implicit default destructor for 'B' first required here}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'B' first required here}} +}; struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'C' first required here}} +}; void f() { - (void)new B; - (void)new C; + (void)new B; + (void)new C; // expected-note {{implicit default destructor for 'C' first required here}} } // Make sure that the key-function computation is consistent when the diff --git a/clang/test/SemaCXX/warn-weak-vtables.cpp b/clang/test/SemaCXX/warn-weak-vtables.cpp index 39333c108ae8798964213a5289e9b44573634e61..c0cfd74a3e528665675703c33203043433f51977 100644 --- a/clang/test/SemaCXX/warn-weak-vtables.cpp +++ b/clang/test/SemaCXX/warn-weak-vtables.cpp @@ -18,4 +18,14 @@ void f() { struct A { virtual void f() { } }; + + A *a; + a->f(); +} + +// Use the vtables +void uses(A &a, B &b, C &c) { + a.f(); + b.f(); + c.f(); } diff --git a/clang/test/SemaTemplate/virtual-member-functions.cpp b/clang/test/SemaTemplate/virtual-member-functions.cpp index 59df3c22aa1cb9a821d8768d852a4fdb600a58b0..974f66484ba151aa05179e18438861077ceecd2f 100644 --- a/clang/test/SemaTemplate/virtual-member-functions.cpp +++ b/clang/test/SemaTemplate/virtual-member-functions.cpp @@ -3,7 +3,7 @@ namespace PR5557 { template struct A { A(); - virtual void anchor(); // expected-note{{instantiation}} + virtual void anchor(); virtual int a(T x); }; template A::A() {} @@ -14,7 +14,7 @@ template int A::a(T x) { } void f(A x) { - x.anchor(); + x.anchor(); // expected-note{{instantiation}} } template @@ -43,7 +43,7 @@ template struct Derived; // expected-note {{in instantiation of member func template struct HasOutOfLineKey { - HasOutOfLineKey() { } // expected-note{{in instantiation of member function 'HasOutOfLineKey::f' requested here}} + HasOutOfLineKey() { } virtual T *f(float *fp); }; @@ -52,4 +52,35 @@ T *HasOutOfLineKey::f(float *fp) { return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}} } -HasOutOfLineKey out_of_line; +HasOutOfLineKey out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey::f' requested here}} + +namespace std { + class type_info; +} + +namespace PR7114 { + class A { virtual ~A(); }; // expected-note{{declared private here}} + + template + class B { + public: + class Inner : public A { }; // expected-error{{base class 'PR7114::A' has private destructor}} + static Inner i; + static const unsigned value = sizeof(i) == 4; + }; + + int f() { return B::value; } + + void test_typeid(B::Inner bfi) { + (void)typeid(bfi); // expected-note{{implicit default destructor}} + } + + template + struct X : A { + void f() { } + }; + + void test_X(X xi, X xf) { + xi.f(); + } +}