More symbol table bugfixes that are impossible to track down. Goody
authorChris Lattner <sabre@nondot.org>
Tue, 23 Oct 2001 02:32:45 +0000 (02:32 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 23 Oct 2001 02:32:45 +0000 (02:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@960 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/SymbolTable.h
lib/VMCore/SymbolTable.cpp

index c53cb785fa67bbae8b9d3fe0b6663bd1c50b469a..ee53f6d5a34f7371d022c73eb656ce5ac47beaf3 100644 (file)
 #include "llvm/ConstPoolVals.h"
 #endif
 
-class Value;
 class Type;
 
-// TODO: Change this back to vector<map<const string, Value *> >
-// Make the vector be a data member, and base it on UniqueID's
-// That should be much more efficient!
-//
 class SymbolTable : public AbstractTypeUser,
                    public map<const Type *, map<const string, Value *> > {
 public:
@@ -47,7 +42,10 @@ public:
   typedef VarMap::iterator type_iterator;
   typedef VarMap::const_iterator type_const_iterator;
 
-  inline SymbolTable(SymbolTable *P = 0) { ParentSymTab = P; }
+  inline SymbolTable(SymbolTable *P = 0) {
+    ParentSymTab = P;
+    InternallyInconsistent = false;
+  }
   ~SymbolTable();
 
   SymbolTable *getParentSymTab() { return ParentSymTab; }
@@ -106,6 +104,15 @@ public:
   void dump() const;  // Debug method, print out symbol table
 
 private:
+  // InternallyInconsistent - There are times when the symbol table is
+  // internally inconsistent with the rest of the program.  In this one case, a
+  // value exists with a Name, and it's not in the symbol table.  When we call
+  // V->setName(""), it tries to remove itself from the symbol table and dies.
+  // We know this is happening, and so if the flag InternallyInconsistent is
+  // set, removal from the symbol table is a noop.
+  //
+  bool InternallyInconsistent;
+
   inline super::value_type operator[](const Type *Ty) {
     assert(0 && "Should not use this operator to access symbol table!");
     return super::value_type();
index ecac7c2a3d1d515f37279c8d536d9f3eebbf6bd8..f84e945e7d63ec56ebbcd0ba6daaa82deb72646b 100644 (file)
@@ -80,6 +80,7 @@ void SymbolTable::remove(Value *N) {
 // removeEntry - Remove a value from the symbol table...
 //
 Value *SymbolTable::removeEntry(iterator Plane, type_iterator Entry) {
+  if (InternallyInconsistent) return 0;
   assert(Plane != super::end() &&
          Entry != Plane->second.end() && "Invalid entry to remove!");
 
@@ -206,37 +207,32 @@ void SymbolTable::refineAbstractType(const DerivedType *OldType,
         // The only thing we are allowing for now is two method prototypes being
         // folded into one.
         //
-        if (Method *ExistM = dyn_cast<Method>(TI->second))
-          if (Method *NewM = dyn_cast<Method>(V.second))
-            if (ExistM->isExternal() && NewM->isExternal()) {
-              // Ok we have two external methods.  Make all uses of the new one
-              // use the old one...
-              //
-              NewM->replaceAllUsesWith(ExistM);
-
-              // Now we just convert it to an unnamed method... which won't get
-              // added to our symbol table.  The problem is that if we call
-              // setName on the method that it will try to remove itself from
-              // the symbol table and die... because it's not in the symtab
-              // right now.  To fix this, we temporarily insert it (by setting
-              // TI's entry to the old value.  Then after it is removed, we
-              // restore ExistM into the symbol table.
-              //
-              if (NewM->getType() == NewType) {
-                TI->second = NewM;     // Add newM to the symtab
-
-                // Remove newM from the symtab
-                NewM->setName("");
-
-                // Readd ExistM to the symbol table....
-                NewPlane.insert(make_pair(V.first, ExistM));
-              } else {
-                NewM->setName("");
-              }
-              continue;
-            }
-        assert(0 && "Two ploanes folded together with overlapping "
-               "value names!");
+        Method *ExistM = dyn_cast<Method>(TI->second);
+        Method *NewM = dyn_cast<Method>(V.second);
+
+        if (ExistM && NewM && ExistM->isExternal() && NewM->isExternal()) {
+          // Ok we have two external methods.  Make all uses of the new one
+          // use the old one...
+          //
+          NewM->replaceAllUsesWith(ExistM);
+          
+          // Now we just convert it to an unnamed method... which won't get
+          // added to our symbol table.  The problem is that if we call
+          // setName on the method that it will try to remove itself from
+          // the symbol table and die... because it's not in the symtab
+          // right now.  To fix this, we have an internally consistent flag
+          // that turns remove into a noop.  Thus the name will get null'd
+          // out, but the symbol table won't get upset.
+          //
+          InternallyInconsistent = true;
+
+          // Remove newM from the symtab
+          NewM->setName("");
+          InternallyInconsistent = false;
+        } else {
+          assert(0 && "Two ploanes folded together with overlapping "
+                 "value names!");
+        }
       } else {
         insertEntry(V.first, NewType, V.second);