summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTConsumer.h12
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp54
-rw-r--r--clang/lib/CodeGen/CGVTables.h10
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp10
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h2
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp7
-rw-r--r--clang/lib/Frontend/CodeGenAction.cpp4
-rw-r--r--clang/lib/Sema/Sema.cpp18
-rw-r--r--clang/lib/Sema/Sema.h43
-rw-r--r--clang/lib/Sema/SemaCXXCast.cpp8
-rw-r--r--clang/lib/Sema/SemaDecl.cpp47
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp198
-rw-r--r--clang/lib/Sema/SemaExpr.cpp8
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp27
-rw-r--r--clang/lib/Sema/SemaInit.cpp9
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp8
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp30
-rw-r--r--clang/test/CodeGenCXX/cxx-apple-kext.cpp2
-rw-r--r--clang/test/CodeGenCXX/rtti-linkage.cpp65
-rw-r--r--clang/test/CodeGenCXX/thunks.cpp2
-rw-r--r--clang/test/CodeGenCXX/virtual-base-destructor-call.cpp1
-rw-r--r--clang/test/CodeGenCXX/virtual-functions-incomplete-types.cpp2
-rw-r--r--clang/test/CodeGenCXX/vtable-layout.cpp1672
-rw-r--r--clang/test/CodeGenCXX/vtable-linkage.cpp76
-rw-r--r--clang/test/SemaCXX/implicit-virtual-member-functions.cpp4
-rw-r--r--clang/test/SemaCXX/virtual-member-functions-key-function.cpp10
-rw-r--r--clang/test/SemaCXX/warn-weak-vtables.cpp10
-rw-r--r--clang/test/SemaTemplate/virtual-member-functions.cpp39
28 files changed, 1266 insertions, 1112 deletions
diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h
index 53bb785c49d..06113954fc4 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 df0f641a50f..368e2483c86 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<CXXMethodDecl>(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 6c18ca83f09..e55377f2fa2 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 6cbc3f67c2d..6dd16e73b49 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<CXXMethodDecl>(D))
- getVTables().EmitVTableRelatedData(GD);
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ if (Method->isVirtual())
+ getVTables().EmitThunks(GD);
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(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 93d8ddf3e48..0e4f4a932ee 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 1e1edc1c482..9905ca6f1dc 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 79d7d5f4c24..86005f280ac 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 91effa44b26..569de3203aa 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<PointerType>())
+ T = Pointer->getPointeeType();
+ if (const RecordType *RecordTy = T->getAs<RecordType>())
+ MarkVTableUsed(Expr->getLocStart(),
+ cast<CXXRecordDecl>(RecordTy->getDecl()));
+ }
+
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(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 9d811a4dbe9..4ef5ebe20a7 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<std::pair<CXXRecordDecl *, SourceLocation>, 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<std::pair<CXXRecordDecl *, SourceLocation>, 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<CXXRecordDecl *, bool> VTablesUsed;
+
+ /// \brief A list of all of the dynamic classes in this translation
+ /// unit.
+ llvm::SmallVector<CXXRecordDecl *, 16> 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 9f8b344562f..1dbdd06eeab 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<CXXRecordDecl>(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<CXXRecordDecl>(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 b4f5d13d2a5..76334e9a125 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<CXXMethodDecl>(FD))
- MaybeMarkVirtualMembersReferenced(Method->getLocation(), Method);
-
+
+ // If this is a constructor, we need a vtable.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
+ MarkVTableUsed(FD->getLocation(), Constructor->getParent());
+ }
+
assert(FD == getCurFunctionDecl() && "Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(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<CXXRecordDecl>(*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<CXXRecordDecl>(Tag) && !Tag->getLexicalDeclContext()->isRecord())
- RecordDynamicClassesWithNoKeyFunction(*this, cast<CXXRecordDecl>(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 7f8d2451588..558746b0fea 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<Stmt>());
-
- MaybeMarkVirtualMembersReferenced(CurrentLocation, CopyAssignOperator);
}
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
@@ -4670,7 +4683,6 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
MultiStmtArg(*this, 0, 0),
/*isStmtExpr=*/false)
.takeAs<Stmt>());
- 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<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
- return true;
- break;
+ // Try to insert this class into the map.
+ Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::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<CXXRecordDecl>(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<CXXRecordDecl>(*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<CXXRecordDecl>(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 73493b60662..13f44b9a8a9 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<CXXDestructorDecl>(D)) {
if (Destructor->isImplicit() && !Destructor->isUsed())
DefineImplicitDestructor(Loc, Destructor);
-
+ if (Destructor->isVirtual())
+ MarkVTableUsed(Loc, Destructor->getParent());
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(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<FunctionDecl>(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 8b17f8483d8..15c21008bed 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<Expr>();
+
+ // 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<RecordType>())
+ MarkVTableUsed(ThrowLoc, cast<CXXRecordDecl>(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 fea7e6129f1..851fb9e8353 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<PointerType>())
+ T = Pointer->getPointeeType();
+ if (const RecordType *RecordTy = T->getAs<RecordType>())
+ S.MarkVTableUsed(CurInitExpr->getLocStart(),
+ cast<CXXRecordDecl>(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 0f3f86dbfd4..9009b4d8977 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<ClassTemplateSpecializationDecl>(
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 589b9956536..0e4dfcb14cb 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 8d67b53657a..4ba69069bed 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 b9eb5b4ad41..d83048d8958 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 <typeinfo>
-// 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 b91ba3239b1..7d2edaa7457 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 7de9dd2a608..22c49a089d0 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 50e04357b39..991c2bc7220 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 f2f5179d4a1..60b46fec39b 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 c75efe228df..02b1d5c7483 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<int>;
void use_F(F<char> &fc) {
F<int> fi;
- (void)fi;
+ fi.foo();
F<long> fl;
(void)fl;
fc.foo();
@@ -81,71 +93,71 @@ void use_F(F<char> &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<char> 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<short> 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<short> 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<long> 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<long> 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<int> 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<int> 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 cb245011a87..f6082e5699c 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 97164d93aff..09a30b93605 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 39333c108ae..c0cfd74a3e5 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<int> &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 59df3c22aa1..974f66484ba 100644
--- a/clang/test/SemaTemplate/virtual-member-functions.cpp
+++ b/clang/test/SemaTemplate/virtual-member-functions.cpp
@@ -3,7 +3,7 @@
namespace PR5557 {
template <class T> struct A {
A();
- virtual void anchor(); // expected-note{{instantiation}}
+ virtual void anchor();
virtual int a(T x);
};
template<class T> A<T>::A() {}
@@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) {
}
void f(A<int> x) {
- x.anchor();
+ x.anchor(); // expected-note{{instantiation}}
}
template<typename T>
@@ -43,7 +43,7 @@ template struct Derived<int>; // expected-note {{in instantiation of member func
template<typename T>
struct HasOutOfLineKey {
- HasOutOfLineKey() { } // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::f' requested here}}
+ HasOutOfLineKey() { }
virtual T *f(float *fp);
};
@@ -52,4 +52,35 @@ T *HasOutOfLineKey<T>::f(float *fp) {
return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}}
}
-HasOutOfLineKey<int> out_of_line;
+HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::f' requested here}}
+
+namespace std {
+ class type_info;
+}
+
+namespace PR7114 {
+ class A { virtual ~A(); }; // expected-note{{declared private here}}
+
+ template<typename T>
+ 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<int>::value; }
+
+ void test_typeid(B<float>::Inner bfi) {
+ (void)typeid(bfi); // expected-note{{implicit default destructor}}
+ }
+
+ template<typename T>
+ struct X : A {
+ void f() { }
+ };
+
+ void test_X(X<int> xi, X<float> xf) {
+ xi.f();
+ }
+}
OpenPOWER on IntegriCloud