diff options
-rw-r--r-- | lib/CodeGen/CGRTTI.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 4 | ||||
-rw-r--r-- | test/CodeGenCXX/weak-extern-typeinfo.cpp | 47 |
4 files changed, 57 insertions, 0 deletions
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<RecordType>(Ty)) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); + if (RD->hasAttr<WeakAttr>()) + 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<VarDecl>(D) && !isa<FunctionDecl>(D)) { + if (isa<CXXRecordDecl>(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<RecordType>(NewBaseType)) + if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl())) + if (RD->hasAttr<WeakAttr>()) + 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 |