COFF: Fix the case where an object defines a weak external and its alias.

This worked before, but only by accident, and only with assertions disabled.
We ended up storing a DefinedRegular symbol in the WeakAlias field,
and never using it as an Undefined.

Differential Revision: http://reviews.llvm.org/D10934

llvm-svn: 241376
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 395d510..3bb3c6f 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -199,7 +199,7 @@
   COFFObj->getSymbolName(Sym, Name);
   auto *U = new (Alloc) Undefined(Name);
   auto *Aux = (const coff_aux_weak_external *)AuxP;
-  U->WeakAlias = cast<Undefined>(SparseSymbolBodies[Aux->TagIndex]);
+  U->WeakAlias = SparseSymbolBodies[Aux->TagIndex];
   return U;
 }
 
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 4a08c49..0bc8ff3 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -126,10 +126,11 @@
     if (!Undef)
       continue;
     StringRef Name = Undef->getName();
-    // A weak alias may have been resovled, so check for that. A weak alias
-    // may be an weak alias to other symbol, so check recursively.
-    for (Undefined *U = Undef->WeakAlias; U; U = U->WeakAlias) {
-      if (auto *D = dyn_cast<Defined>(U->repl())) {
+    // A weak alias may have been resolved, so check for that. A weak alias
+    // may be a weak alias to another symbol, so check recursively.
+    for (SymbolBody *A = Undef->WeakAlias; A;
+         A = cast<Undefined>(A)->WeakAlias) {
+      if (auto *D = dyn_cast<Defined>(A->repl())) {
         Sym->Body = D;
         goto next;
       }
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 459d04c..e695c39 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -253,7 +253,7 @@
   // undefined symbol a second chance if it would remain undefined.
   // If it remains undefined, it'll be replaced with whatever the
   // Alias pointer points to.
-  Undefined *WeakAlias = nullptr;
+  SymbolBody *WeakAlias = nullptr;
 };
 
 // Windows-specific classes.
diff --git a/lld/test/COFF/weak-external.test b/lld/test/COFF/weak-external.test
new file mode 100644
index 0000000..294fecd
--- /dev/null
+++ b/lld/test/COFF/weak-external.test
@@ -0,0 +1,29 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: lld -flavor link2 /out:%t.exe /entry:g /subsystem:console %t.obj
+
+---
+header:          
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [  ]
+sections:        
+  - Name:            '.text'
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       16
+    SectionData:     00
+symbols:         
+  - Name:            'f'
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            'g'
+    Value:           0
+    SectionNumber:   0
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_WEAK_EXTERNAL
+    WeakExternal:    
+      TagIndex:        0
+      Characteristics: IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
+...