diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 22 | ||||
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 18 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 32 |
6 files changed, 51 insertions, 37 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index bbbb19a35b4..b30d335918a 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -643,23 +643,15 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { return C.getPointerType(ClassTy); } -static bool MethodHasBody(const CXXMethodDecl *MD, const FunctionDecl *&fn) { - // Simple case: function has a body - if (MD->getBody(fn)) - return true; - - // Complex case: function is an instantiation of a function which has a - // body, but the definition hasn't been instantiated. - const FunctionDecl *PatternDecl = MD->getTemplateInstantiationPattern(); - if (PatternDecl && PatternDecl->getBody(fn)) - return true; - - return false; -} - bool CXXMethodDecl::hasInlineBody() const { + // If this function is a template instantiation, look at the template from + // which it was instantiated. + const FunctionDecl *CheckFn = getTemplateInstantiationPattern(); + if (!CheckFn) + CheckFn = this; + const FunctionDecl *fn; - return MethodHasBody(this, fn) && !fn->isOutOfLine(); + return CheckFn->getBody(fn) && !fn->isOutOfLine(); } CXXBaseOrMemberInitializer:: diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index c914f3f82e8..cfd89eaed35 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -719,11 +719,6 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { // If a class isnt' polymorphic it doesn't have a key function. if (!RD->isPolymorphic()) return 0; - - // A class template specialization or instantation does not have a key - // function. - if (RD->getTemplateSpecializationKind() != TSK_Undeclared) - return 0; // A class inside an anonymous namespace doesn't have a key function. (Or // at least, there's no point to assigning a key function to such a class; @@ -741,13 +736,13 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { if (MD->isPure()) continue; - if (MD->isInlineSpecified()) - continue; - // Ignore implicit member functions, they are always marked as inline, but // they don't have a body until they're defined. if (MD->isImplicit()) continue; + + if (MD->isInlineSpecified()) + continue; if (MD->hasInlineBody()) continue; diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index ba5a0c35439..ca148da9560 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -1493,8 +1493,22 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { llvm::GlobalVariable::LinkageTypes Linkage; if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) Linkage = llvm::GlobalVariable::InternalLinkage; - else if (KeyFunction && !MD->isInlined()) - Linkage = llvm::GlobalVariable::ExternalLinkage; + else if (KeyFunction && !MD->isInlined()) { + switch (MD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + Linkage = llvm::GlobalVariable::ExternalLinkage; + break; + + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + // FIXME: could an explicit instantiation declaration imply + // available_externally linkage? + case TSK_ExplicitInstantiationDefinition: + Linkage = llvm::GlobalVariable::WeakODRLinkage; + break; + } + } else Linkage = llvm::GlobalVariable::WeakODRLinkage; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16a01cfd58f..85d57e7cbec 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -547,7 +547,8 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { const CXXRecordDecl *RD = MD->getParent(); if (MD->isOutOfLine() && RD->isDynamicClass()) { const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD); - if (KeyFunction == MD->getCanonicalDecl()) + if (KeyFunction && + KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl()) return false; } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a15c5fea213..0fc61e3b587 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3749,7 +3749,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { if (getLangOptions().CPlusPlus) { // Make sure we mark the destructor as used if necessary. QualType InitType = VDecl->getType(); - if (const ArrayType *Array = Context.getAsArrayType(InitType)) + while (const ArrayType *Array = Context.getAsArrayType(InitType)) InitType = Context.getBaseElementType(Array); if (InitType->isRecordType()) FinalizeVarWithDestructor(VDecl, InitType); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 204d7764682..ecf95d7eb66 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5702,19 +5702,31 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, ClassesWithUnmarkedVirtualMembers.insert(std::make_pair(RD, Loc)); return; } - - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - if (!KeyFunction) { - // This record does not have a key function, so we assume that the vtable - // will be emitted when it's used by the constructor. - if (!isa<CXXConstructorDecl>(MD)) + switch (RD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: { + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); + + if (!KeyFunction) { + // This record does not have a key function, so we assume that the vtable + // will be emitted when it's used by the constructor. + if (!isa<CXXConstructorDecl>(MD)) + return; + } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) { + // We don't have the right key function. return; - } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) { - // We don't have the right key function. - return; + } + break; } - + + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + // Always mark the virtual members of an instantiated template. + break; + } + // Mark the members as referenced. MarkVirtualMembersReferenced(Loc, RD); ClassesWithUnmarkedVirtualMembers.erase(RD); |