MS ABI: Update the thunk linkage computation
As suggested by Reid:
- class has GVA_Internal linkage -> internal
- thunk has return adjustment -> weak_odr, to handle evil corner case [1]
- all other normal methods -> linkonce_odr
1. Evil corner case:
struct Incomplete;
struct A { int a; virtual A *bar(); };
struct B { int b; virtual B *foo(Incomplete); };
struct C : A, B { int c; virtual C *foo(Incomplete); };
C c;
Here, the thunk for C::foo() will be emitted when C::foo() is defined, which
might be in a different translation unit, so it needs to be weak_odr.
Differential Revision: http://reviews.llvm.org/D3992
llvm-svn: 210368
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 615ec23..8268774 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -359,7 +359,8 @@
/// base tables.
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;
- virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) = 0;
+ virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
+ GlobalDecl GD, bool ReturnAdjustment) = 0;
virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF,
llvm::Value *This,
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 8984a70..91e6a18 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -382,12 +382,14 @@
// FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly.
if (!UseAvailableExternallyLinkage) {
CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
- CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable);
+ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
+ !Thunk.Return.isEmpty());
}
} else {
// Normal thunk body generation.
CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk);
- CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable);
+ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
+ !Thunk.Return.isEmpty());
}
}
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 951174b..86eb36d 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -174,7 +174,8 @@
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
- void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) override {
+ void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
+ bool ReturnAdjustment) override {
// Allow inlining of thunks by emitting them with available_externally
// linkage together with vtables when needed.
if (ForVTable)
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 5fd9e97..ffcf76e 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -201,11 +201,20 @@
void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD,
llvm::GlobalVariable *GV) const;
- void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) override {
- Thunk->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
-
+ void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
+ GlobalDecl GD, bool ReturnAdjustment) override {
// Never dllimport/dllexport thunks.
Thunk->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+
+ GVALinkage Linkage =
+ getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl()));
+
+ if (Linkage == GVA_Internal)
+ Thunk->setLinkage(llvm::GlobalValue::InternalLinkage);
+ else if (ReturnAdjustment)
+ Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);
+ else
+ Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
}
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,