Postpone the deletion of the old name in StructType::setName to allow using a slice of the old name.

Fixes PR13522. Add a rudimentary unit test to exercise the behavior.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161296 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2012-08-04 09:47:02 +00:00
parent a6273f1a4a
commit 189f231a4b
2 changed files with 51 additions and 11 deletions

View File

@ -464,19 +464,26 @@ void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) {
void StructType::setName(StringRef Name) { void StructType::setName(StringRef Name) {
if (Name == getName()) return; if (Name == getName()) return;
// If this struct already had a name, remove its symbol table entry. StringMap<StructType *> &SymbolTable = getContext().pImpl->NamedStructTypes;
if (SymbolTableEntry) { typedef StringMap<StructType *>::MapEntryTy EntryTy;
getContext().pImpl->NamedStructTypes.erase(getName());
SymbolTableEntry = 0; // If this struct already had a name, remove its symbol table entry. Don't
// delete the data yet because it may be part of the new name.
if (SymbolTableEntry)
SymbolTable.remove((EntryTy *)SymbolTableEntry);
// If this is just removing the name, we're done.
if (Name.empty()) {
if (SymbolTableEntry) {
// Delete the old string data.
((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator());
SymbolTableEntry = 0;
}
return;
} }
// If this is just removing the name, we're done.
if (Name.empty())
return;
// Look up the entry for the name. // Look up the entry for the name.
StringMapEntry<StructType*> *Entry = EntryTy *Entry = &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name);
&getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name);
// While we have a name collision, try a random rename. // While we have a name collision, try a random rename.
if (Entry->getValue()) { if (Entry->getValue()) {
@ -497,7 +504,10 @@ void StructType::setName(StringRef Name) {
// Okay, we found an entry that isn't used. It's us! // Okay, we found an entry that isn't used. It's us!
Entry->setValue(this); Entry->setValue(this);
// Delete the old string data.
if (SymbolTableEntry)
((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator());
SymbolTableEntry = Entry; SymbolTableEntry = Entry;
} }

View File

@ -0,0 +1,30 @@
//===- llvm/unittest/VMCore/TypesTest.cpp - Type unit tests ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(TypesTest, StructType) {
LLVMContext C;
// PR13522
StructType *Struct = StructType::create(C, "FooBar");
EXPECT_EQ("FooBar", Struct->getName());
Struct->setName(Struct->getName().substr(0, 3));
EXPECT_EQ("Foo", Struct->getName());
Struct->setName("");
EXPECT_TRUE(Struct->getName().empty());
EXPECT_FALSE(Struct->hasName());
}
} // end anonymous namespace