From 13c7fcceb9fd96f5be03af038ce16b05bb5e9598 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 21 Oct 2011 22:27:12 +0000 Subject: [PATCH] c++: support gcc's application of weak attribute on class declaration which forces any such class and any class that inherits from such a class to have their typeinfo symbols be marked as weak. // rdar://10246395 A test/CodeGenCXX/weak-extern-typeinfo.cpp M lib/Sema/SemaDeclCXX.cpp M lib/Sema/SemaDeclAttr.cpp M lib/CodeGen/CGRTTI.cpp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142693 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGRTTI.cpp | 2 + lib/Sema/SemaDeclAttr.cpp | 4 ++ lib/Sema/SemaDeclCXX.cpp | 4 ++ test/CodeGenCXX/weak-extern-typeinfo.cpp | 47 ++++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 test/CodeGenCXX/weak-extern-typeinfo.cpp diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 1b3cb08284..d9790d0b9e 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -336,6 +336,8 @@ getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) { if (const RecordType *Record = dyn_cast(Ty)) { const CXXRecordDecl *RD = cast(Record->getDecl()); + if (RD->hasAttr()) + return llvm::GlobalValue::WeakODRLinkage; if (RD->isDynamicClass()) return CGM.getVTableLinkage(RD); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b83b716fdf..d801664ad6 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1914,6 +1914,10 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { } if (!isa(D) && !isa(D)) { + if (isa(D)) { + D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); + return; + } S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariableOrFunction; return; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f445e9ff5b..2896e9f585 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1151,6 +1151,10 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Okay, add this new base class. KnownBaseTypes[NewBaseType] = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; + if (const RecordType *Record = dyn_cast(NewBaseType)) + if (const CXXRecordDecl *RD = cast(Record->getDecl())) + if (RD->hasAttr()) + Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context)); } } diff --git a/test/CodeGenCXX/weak-extern-typeinfo.cpp b/test/CodeGenCXX/weak-extern-typeinfo.cpp new file mode 100644 index 0000000000..3c3406e559 --- /dev/null +++ b/test/CodeGenCXX/weak-extern-typeinfo.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// rdar://10246395 + +#define WEAK __attribute__ ((weak)) + +class WEAK A { + virtual void foo(); +}; + +class B : public A { + virtual void foo(); +}; +void A::foo() { } +void B::foo() { } + +class T {}; +class T1 {}; + +class C : public T1, public B, public T { + virtual void foo(); +}; +void C::foo() { } + +class V1 : public virtual A { + virtual void foo(); +}; + +class V2 : public virtual V1 { + virtual void foo(); +}; +void V1::foo() { } +void V2::foo() { } + +// CHECK: @_ZTS1A = weak_odr constant +// CHECK: @_ZTI1A = weak_odr unnamed_addr constant +// CHECK: @_ZTS1B = weak_odr constant +// CHECK: @_ZTI1B = weak_odr unnamed_addr constant +// CHECK: @_ZTS1C = weak_odr constant +// CHECK: @_ZTS2T1 = linkonce_odr constant +// CHECK: @_ZTI2T1 = linkonce_odr unnamed_addr constant +// CHECK: @_ZTS1T = linkonce_odr constant +// CHECK: @_ZTI1T = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI1C = weak_odr unnamed_addr constant +// CHECK: @_ZTS2V1 = weak_odr constant +// CHECK: @_ZTI2V1 = weak_odr unnamed_addr constant +// CHECK: @_ZTS2V2 = weak_odr constant +// CHECK: @_ZTI2V2 = weak_odr unnamed_addr constant -- 2.50.1