Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -562,9 +562,9 @@ llvm::Value *MemFnPtr, const MemberPointerType *MPT) { CGBuilderTy &Builder = CGF.Builder; - const FunctionProtoType *FPT = + const FunctionProtoType *FPT = MPT->getPointeeType()->getAs(); - const CXXRecordDecl *RD = + const CXXRecordDecl *RD = cast(MPT->getClass()->getAs()->getDecl()); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( @@ -591,10 +591,10 @@ Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); ThisPtrForCall = This; - + // Load the function pointer. llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); - + // If the LSB in the function pointer is 1, the function pointer points to // a virtual function. llvm::Value *IsVirtual; @@ -642,7 +642,7 @@ CGF.EmitBlock(FnNonVirtual); llvm::Value *NonVirtualFn = Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); - + // We're done. CGF.EmitBlock(FnEnd); llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2); @@ -807,7 +807,7 @@ ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { // Itanium C++ ABI 2.3: // A NULL pointer is represented as -1. - if (MPT->isMemberDataPointer()) + if (MPT->isMemberDataPointer()) return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true); llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0); @@ -884,7 +884,7 @@ (UseARMMethodPtrABI ? 2 : 1) * ThisAdjustment.getQuantity()); } - + return llvm::ConstantStruct::getAnon(MemPtr); } @@ -943,7 +943,7 @@ // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) // The inequality tautologies have exactly the same structure, except // applying De Morgan's laws. - + llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); @@ -996,7 +996,7 @@ llvm::Constant::getAllOnesValue(MemPtr->getType()); return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); } - + // In Itanium, a member function pointer is not null if 'ptr' is not null. llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); @@ -1154,9 +1154,9 @@ // const abi::__class_type_info *src, // const abi::__class_type_info *dst, // std::ptrdiff_t src2dst_offset); - + llvm::Type *Int8PtrTy = CGF.Int8PtrTy; - llvm::Type *PtrDiffTy = + llvm::Type *PtrDiffTy = CGF.ConvertType(CGF.getContext().getPointerDiffType()); llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy }; @@ -1636,6 +1636,7 @@ VTable = CGM.CreateOrReplaceCXXRuntimeVariable( Name, VTableType, llvm::GlobalValue::ExternalLinkage); VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + CGM.setGlobalVisibility(VTable, RD); if (RD->hasAttr()) VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); @@ -2139,19 +2140,19 @@ CGF.EmitBlock(InitCheckBlock); // Variables used when coping with thread-safe statics and exceptions. - if (threadsafe) { + if (threadsafe) { // Call __cxa_guard_acquire. llvm::Value *V = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard); - + llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); - + Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), InitBlock, EndBlock); - + // Call __cxa_guard_abort along the exceptional edge. CGF.EHStack.pushCleanup(EHCleanup, guard); - + CGF.EmitBlock(InitBlock); } @@ -2464,11 +2465,11 @@ /// if it's a base constructor or destructor with virtual bases. bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) { const CXXMethodDecl *MD = cast(GD.getDecl()); - + // We don't have any virtual bases, just return early. if (!MD->getParent()->getNumVBases()) return false; - + // Check if we have a base constructor. if (isa(MD) && GD.getCtorType() == Ctor_Base) return true; @@ -2476,7 +2477,7 @@ // Check if we have a base destructor. if (isa(MD) && GD.getDtorType() == Dtor_Base) return true; - + return false; } Index: test/CodeGen/push-hidden-visibility-subclass.cpp =================================================================== --- /dev/null +++ test/CodeGen/push-hidden-visibility-subclass.cpp @@ -0,0 +1,21 @@ +// RUN: %clang -S -emit-llvm -o %t %s +// RUN: FileCheck --input-file=%t %s + +#pragma GCC visibility push(hidden) + +struct Base { + virtual ~Base() = default; + virtual void* Alloc() = 0; +}; + +class Child : public Base { +public: + Child() = default; + void* Alloc(); +}; + +void test() { + Child x; +} + +// CHECK: @_ZTV5Child = external hidden unnamed_addr constant