summaryrefslogtreecommitdiff
path: root/lib/Linker
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2008-07-05 23:03:21 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2008-07-05 23:03:21 +0000
commit194c2cef8a0036dd4e6295d048f37d6130f92389 (patch)
treef963b917e2416cb74299ee8419f503c70fba0a4a /lib/Linker
parent315b333deaeae84dc35d7d9588ee5cf0bb35c2dc (diff)
downloadllvm-194c2cef8a0036dd4e6295d048f37d6130f92389.tar.gz
llvm-194c2cef8a0036dd4e6295d048f37d6130f92389.tar.bz2
llvm-194c2cef8a0036dd4e6295d048f37d6130f92389.tar.xz
Properly link alias and function decls. This fixes PR2146
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53154 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Linker')
-rw-r--r--lib/Linker/LinkModules.cpp35
1 files changed, 27 insertions, 8 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index e02f7fe44c..a915a8b873 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -899,21 +899,30 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src,
for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) {
const Function *SF = I; // SrcFunction
- Function *DF = 0;
+ GlobalValue *DGV = 0;
Value *MappedDF;
// If this function is internal or has no name, it doesn't participate in
// linkage.
if (SF->hasName() && !SF->hasInternalLinkage()) {
// Check to see if may have to link the function.
- DF = Dest->getFunction(SF->getName());
- if (DF && DF->hasInternalLinkage())
- DF = 0;
+ DGV = Dest->getFunction(SF->getName());
}
-
+
+ // Check to see if may have to link the function with the alias
+ if (!DGV && SF->hasName() && !SF->hasInternalLinkage()) {
+ DGV = Dest->getNamedAlias(SF->getName());
+ if (DGV && DGV->getType() != SF->getType())
+ // If types don't agree due to opaque types, try to resolve them.
+ RecursiveResolveTypes(SF->getType(), DGV->getType());
+ }
+
+ if (DGV && DGV->hasInternalLinkage())
+ DGV = 0;
+
// If there is no linkage to be performed, just bring over SF without
// modifying it.
- if (DF == 0) {
+ if (DGV == 0) {
// Function does not already exist, simply insert an function signature
// identical to SF into the dest module.
Function *NewDF = Function::Create(SF->getFunctionType(),
@@ -930,9 +939,19 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src,
// ... and remember this mapping...
ValueMap[SF] = NewDF;
continue;
+ } else if (GlobalAlias *DGA = dyn_cast<GlobalAlias>(DGV)) {
+ // SF is global, but DF is alias. The only valid mapping is when SF is
+ // external declaration, which is effectively a no-op.
+ if (!SF->isDeclaration())
+ return Error(Err, "Function-Alias Collision on '" + SF->getName() +
+ "': symbol multiple defined");
+
+ // Make sure to remember this mapping...
+ ValueMap[SF] = DGA;
+ continue;
}
-
-
+
+ Function* DF = cast<Function>(DGV);
// If types don't agree because of opaque, try to resolve them.
if (SF->getType() != DF->getType())
RecursiveResolveTypes(SF->getType(), DF->getType());