Don't query names of empty symbols

This makes it possible to return a reference from TSymbol::name()
instead of a pointer. This is safer since it completely avoids the
possibility of a nullptr dereference. An assert is making sure that
the function is not being called for empty symbols.

BUG=angleproject:2267
TEST=angle_unittests

Change-Id: I44279f65989dbb828322843fc0216ba84d91dedf
Reviewed-on: https://chromium-review.googlesource.com/836894
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ASTMetadataHLSL.cpp b/src/compiler/translator/ASTMetadataHLSL.cpp
index d1ae057..a15fc36 100644
--- a/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -129,7 +129,7 @@
             }
             else if (node->getOp() == EOpCallBuiltInFunction)
             {
-                if (mGradientBuiltinFunctions.find(*node->getFunction()->name()) !=
+                if (mGradientBuiltinFunctions.find(node->getFunction()->name()) !=
                     mGradientBuiltinFunctions.end())
                 {
                     onGradient();
diff --git a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
index 9299019..863b343 100644
--- a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -128,7 +128,7 @@
             changedFunction.returnValueVariable =
                 new TVariable(mSymbolTable, mReturnValueVariableName, returnValueVariableType,
                               SymbolType::AngleInternal);
-            changedFunction.func = new TFunction(mSymbolTable, node->getFunction()->name(),
+            changedFunction.func = new TFunction(mSymbolTable, &node->getFunction()->name(),
                                                  StaticType::GetBasic<EbtVoid>(),
                                                  node->getFunction()->symbolType(), false);
             mChangedFunctions[functionId.get()] = changedFunction;
diff --git a/src/compiler/translator/CallDAG.cpp b/src/compiler/translator/CallDAG.cpp
index c4c8e83..8209cf2 100644
--- a/src/compiler/translator/CallDAG.cpp
+++ b/src/compiler/translator/CallDAG.cpp
@@ -108,12 +108,12 @@
             if (it == mFunctions.end())
             {
                 mCurrentFunction       = &mFunctions[node->getFunction()->uniqueId().get()];
-                mCurrentFunction->name = *node->getFunction()->name();
+                mCurrentFunction->name = node->getFunction()->name();
             }
             else
             {
                 mCurrentFunction = &it->second;
-                ASSERT(mCurrentFunction->name == *node->getFunction()->name());
+                ASSERT(mCurrentFunction->name == node->getFunction()->name());
             }
 
             mCurrentFunction->node = node;
@@ -135,7 +135,7 @@
 
         // Function declaration, create an empty record.
         auto &record = mFunctions[node->getFunction()->uniqueId().get()];
-        record.name  = *node->getFunction()->name();
+        record.name  = node->getFunction()->name();
 
         // No need to traverse the parameters.
         return false;
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 7a8750b..0c0dba2 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -91,8 +91,7 @@
                                              std::vector<InterfaceBlock> *infoList)
 {
     ASSERT(interfaceBlock);
-    ASSERT(interfaceBlock->name());
-    InterfaceBlock *namedBlock = FindVariable(*interfaceBlock->name(), infoList);
+    InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
     ASSERT(namedBlock);
 
     // Set static use on the parent interface block here
@@ -576,7 +575,7 @@
         variableOut->type       = GL_NONE;
         if (structure->symbolType() != SymbolType::Empty)
         {
-            variableOut->structName = structure->name()->c_str();
+            variableOut->structName = structure->name().c_str();
         }
 
         const TFieldList &fields = structure->fields();
@@ -586,7 +585,7 @@
             // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
             // ShaderVariable objects.
             ShaderVariable fieldVariable;
-            setCommonVariableProperties(*field->type(), TName(&field->name()), &fieldVariable);
+            setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
             variableOut->fields.push_back(fieldVariable);
         }
     }
@@ -665,7 +664,7 @@
     const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
     ASSERT(blockType);
 
-    interfaceBlock->name         = blockType->name()->c_str();
+    interfaceBlock->name         = blockType->name().c_str();
     interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
     interfaceBlock->instanceName = instanceName.c_str();
     ASSERT(!interfaceBlockType.isArrayOfArrays());  // Disallowed by GLSL ES 3.10 section 4.3.9
@@ -687,7 +686,7 @@
         const TType &fieldType = *field->type();
 
         InterfaceBlockField fieldVariable;
-        setCommonVariableProperties(fieldType, TName(&field->name()), &fieldVariable);
+        setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
         fieldVariable.isRowMajorLayout =
             (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
         interfaceBlock->fields.push_back(fieldVariable);
@@ -835,7 +834,7 @@
         const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
         if (!namedBlock)
         {
-            namedBlock = findNamedInterfaceBlock(*interfaceBlock->name());
+            namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
         }
         ASSERT(namedBlock);
         namedBlock->staticUse   = true;
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 18127bf..dc6139c 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -144,12 +144,13 @@
 
 }  // namespace anonymous
 
-TName::TName(const TString *name) : mName(name ? (*name) : ""), mIsInternal(false)
+TName::TName(const TString &name) : mName(name), mIsInternal(false)
 {
 }
 
 TName::TName(const TSymbol *symbol)
-    : mName(*symbol->name()), mIsInternal(symbol->symbolType() == SymbolType::AngleInternal)
+    : mName(symbol->symbolType() == SymbolType::Empty ? "" : symbol->name()),
+      mIsInternal(symbol->symbolType() == SymbolType::AngleInternal)
 {
 }
 
@@ -281,12 +282,8 @@
 }
 
 TIntermSymbol::TIntermSymbol(const TVariable *variable)
-    : TIntermTyped(variable->getType()), mVariable(variable), mSymbol(variable->name())
+    : TIntermTyped(variable->getType()), mVariable(variable), mSymbol(variable)
 {
-    if (variable->symbolType() == SymbolType::AngleInternal)
-    {
-        mSymbol.setInternal(true);
-    }
 }
 
 const TSymbolUniqueId &TIntermSymbol::uniqueId() const
@@ -461,7 +458,7 @@
     }
     // ESSL 3.0 spec section 8: textureSize always gets highp precision.
     // All other functions that take a sampler are assumed to be texture functions.
-    if (mFunction->name()->find("textureSize") == 0)
+    if (mFunction->name().find("textureSize") == 0)
         mType.setPrecision(EbpHigh);
     else
         mType.setPrecision(precision);
@@ -475,7 +472,7 @@
         case EOpCallInternalRawFunction:
         case EOpCallBuiltInFunction:
         case EOpCallFunctionInAST:
-            return TFunction::GetMangledNameFromCall(*mFunction->name(), mArguments);
+            return TFunction::GetMangledNameFromCall(mFunction->name(), mArguments);
         default:
             TString opString = GetOperatorString(mOp);
             return TFunction::GetMangledNameFromCall(opString, mArguments);
@@ -490,7 +487,7 @@
         case EOpCallInternalRawFunction:
         case EOpCallBuiltInFunction:
         case EOpCallFunctionInAST:
-            return mFunction->name()->c_str();
+            return mFunction->name().c_str();
         default:
             return GetOperatorString(mOp);
     }
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 290476e..170c88c 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -66,7 +66,7 @@
 {
   public:
     POOL_ALLOCATOR_NEW_DELETE();
-    explicit TName(const TString *name);
+    explicit TName(const TString &name);
     explicit TName(const TSymbol *symbol);
     TName() : mName(), mIsInternal(false) {}
     TName(const TName &) = default;
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index db5519e..bd2169d 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -585,7 +585,7 @@
                 TString fieldName = field->name();
                 if (structure->symbolType() == SymbolType::UserDefined ||
                     structure->symbolType() == SymbolType::Empty)
-                    fieldName = hashName(TName(&fieldName));
+                    fieldName = hashName(TName(fieldName));
 
                 out << fieldName;
                 visitChildren = false;
@@ -604,11 +604,11 @@
                 ASSERT(interfaceBlock->symbolType() != SymbolType::Empty);
                 if (interfaceBlock->symbolType() == SymbolType::UserDefined)
                 {
-                    fieldName = hashName(TName(&fieldName));
+                    fieldName = hashName(TName(fieldName));
                 }
                 else
                 {
-                    ASSERT(*interfaceBlock->name() == "gl_PerVertex");
+                    ASSERT(interfaceBlock->name() == "gl_PerVertex");
                 }
 
                 out << fieldName;
@@ -938,7 +938,7 @@
             {
                 if (node->getOp() == EOpCallBuiltInFunction)
                 {
-                    out << translateTextureFunction(*node->getFunction()->name());
+                    out << translateTextureFunction(node->getFunction()->name());
                 }
                 else
                 {
@@ -1147,7 +1147,7 @@
 {
     if (func->isMain())
     {
-        return *func->name();
+        return func->name();
     }
     else
     {
@@ -1170,14 +1170,20 @@
 {
     TInfoSinkBase &out = objSink();
 
-    out << "struct " << hashName(TName(structure->name())) << "{\n";
+    out << "struct ";
+
+    if (structure->symbolType() != SymbolType::Empty)
+    {
+        out << hashName(TName(structure->name())) << " ";
+    }
+    out << "{\n";
     const TFieldList &fields = structure->fields();
     for (size_t i = 0; i < fields.size(); ++i)
     {
         const TField *field = fields[i];
         if (writeVariablePrecision(field->type()->getPrecision()))
             out << " ";
-        out << getTypeName(*field->type()) << " " << hashName(TName(&field->name()));
+        out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
         if (field->type()->isArray())
             out << ArrayString(*field->type());
         out << ";\n";
@@ -1257,7 +1263,7 @@
 
         if (writeVariablePrecision(field->type()->getPrecision()))
             out << " ";
-        out << getTypeName(*field->type()) << " " << hashName(TName(&field->name()));
+        out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
         if (field->type()->isArray())
             out << ArrayString(*field->type());
         out << ";\n";
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 9df5186..571b018 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -341,9 +341,8 @@
     {
         TInterfaceBlock *interfaceBlock =
             mappedStruct.blockDeclarator->getType().getInterfaceBlock();
-        const TString &interfaceBlockName = *interfaceBlock->name();
         const TName &instanceName         = mappedStruct.blockDeclarator->getName();
-        if (mReferencedUniformBlocks.count(interfaceBlockName) == 0)
+        if (mReferencedUniformBlocks.count(interfaceBlock->name()) == 0)
         {
             continue;
         }
@@ -380,7 +379,7 @@
 
             TType *structType = mappedStruct.field->type();
             mappedStructs +=
-                "static " + Decorate(*structType->getStruct()->name()) + " " + mappedName;
+                "static " + Decorate(structType->getStruct()->name()) + " " + mappedName;
 
             if (structType->isArray())
             {
@@ -889,7 +888,7 @@
 
             if (interfaceBlock)
             {
-                mReferencedUniformBlocks[*interfaceBlock->name()] = node;
+                mReferencedUniformBlocks[interfaceBlock->name()] = node;
             }
             else
             {
@@ -1237,7 +1236,7 @@
                 {
                     TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
                     TIntermSymbol *instanceArraySymbol = node->getLeft()->getAsSymbolNode();
-                    mReferencedUniformBlocks[*interfaceBlock->name()] = instanceArraySymbol;
+                    mReferencedUniformBlocks[interfaceBlock->name()] = instanceArraySymbol;
                     const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
                     out << mUniformHLSL->UniformBlockInstanceString(
                         instanceArraySymbol->getSymbol(), arrayIndex);
@@ -1925,16 +1924,16 @@
             }
             else if (node->getFunction()->isImageFunction())
             {
-                const TString *name       = node->getFunction()->name();
+                const TString &name       = node->getFunction()->name();
                 TType type                = (*arguments)[0]->getAsTyped()->getType();
                 TString imageFunctionName = mImageFunctionHLSL->useImageFunction(
-                    *name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
+                    name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
                     type.getMemoryQualifier().readonly);
                 out << imageFunctionName << "(";
             }
             else
             {
-                const TString *name    = node->getFunction()->name();
+                const TString &name    = node->getFunction()->name();
                 TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType();
                 int coords = 0;  // textureSize(gsampler2DMS) doesn't have a second argument.
                 if (arguments->size() > 1)
@@ -1942,7 +1941,7 @@
                     coords = (*arguments)[1]->getAsTyped()->getNominalSize();
                 }
                 TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction(
-                    *name, samplerType, coords, arguments->size(), lod0, mShaderType);
+                    name, samplerType, coords, arguments->size(), lod0, mShaderType);
                 out << textureFunctionName << "(";
             }
 
diff --git a/src/compiler/translator/OutputTree.cpp b/src/compiler/translator/OutputTree.cpp
index 4afff03..750f1d6 100644
--- a/src/compiler/translator/OutputTree.cpp
+++ b/src/compiler/translator/OutputTree.cpp
@@ -17,7 +17,7 @@
 {
     const char *internal =
         (func->symbolType() == SymbolType::AngleInternal) ? " (internal function)" : "";
-    out << str << internal << ": " << *func->name() << " (symbol id " << func->uniqueId().get()
+    out << str << internal << ": " << func->name() << " (symbol id " << func->uniqueId().get()
         << ")";
 }
 
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 5aa6882..6274cf7 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -3150,8 +3150,7 @@
     const TSourceLoc &location,
     bool insertParametersToSymbolTable)
 {
-    ASSERT(function.name());
-    checkIsNotReserved(location, *function.name());
+    checkIsNotReserved(location, function.name());
 
     TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
     prototype->setLine(location);
@@ -3243,7 +3242,7 @@
     if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
     {
         error(location, "function does not return a value:",
-              functionPrototype->getFunction()->name()->c_str());
+              functionPrototype->getFunction()->name().c_str());
     }
 
     if (functionBody == nullptr)
@@ -3265,13 +3264,12 @@
 {
     ASSERT(function);
     ASSERT(*function);
-    ASSERT((*function)->name());
     const TSymbol *builtIn =
         symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
 
     if (builtIn)
     {
-        error(location, "built-in functions cannot be redefined", (*function)->name()->c_str());
+        error(location, "built-in functions cannot be redefined", (*function)->name().c_str());
     }
     else
     {
@@ -3293,7 +3291,7 @@
 
         if ((*function)->isDefined())
         {
-            error(location, "function already has a body", (*function)->name()->c_str());
+            error(location, "function already has a body", (*function)->name().c_str());
         }
 
         (*function)->setDefined();
@@ -3320,8 +3318,6 @@
     TFunction *prevDec =
         static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
 
-    ASSERT(function->name() != nullptr);
-
     for (size_t i = 0u; i < function->getParamCount(); ++i)
     {
         auto &param = function->getParam(i);
@@ -3329,17 +3325,17 @@
         {
             // ESSL 3.00.6 section 12.10.
             error(location, "Function parameter type cannot be a structure definition",
-                  function->name()->c_str());
+                  function->name().c_str());
         }
     }
 
     if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltInForShaderVersion(
-                                         function->name()->c_str(), getShaderVersion()))
+                                         function->name().c_str(), getShaderVersion()))
     {
         // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
         // Therefore overloading or redefining builtin functions is an error.
         error(location, "Name of a built-in function cannot be redeclared as function",
-              function->name()->c_str());
+              function->name().c_str());
     }
     else if (prevDec)
     {
@@ -3363,12 +3359,12 @@
     //
     // Check for previously declared variables using the same name.
     //
-    TSymbol *prevSym = symbolTable.find(*function->name(), getShaderVersion());
+    TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion());
     if (prevSym)
     {
         if (!prevSym->isFunction())
         {
-            error(location, "redefinition of a function", function->name()->c_str());
+            error(location, "redefinition of a function", function->name().c_str());
         }
     }
     else
@@ -3382,7 +3378,7 @@
     symbolTable.getOuterLevel()->insert(function);
 
     // Raise error message if main function takes any parameters or return anything other than void
-    if (*function->name() == "main")
+    if (function->name() == "main")
     {
         if (function->getParamCount() > 0)
         {
@@ -3906,7 +3902,7 @@
         else
         {
             reasonStream << "Reference of struct type "
-                         << field.type()->getStruct()->name()->c_str();
+                         << field.type()->getStruct()->name().c_str();
         }
         reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
         std::string reason = reasonStream.str();
@@ -5485,7 +5481,7 @@
 void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name        = *functionCall->getFunction()->name();
+    const TString &name        = functionCall->getFunction()->name();
     bool isTextureGather       = (name == "textureGather");
     bool isTextureGatherOffset = (name == "textureGatherOffset");
     if (isTextureGather || isTextureGatherOffset)
@@ -5551,7 +5547,7 @@
 void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name                    = *functionCall->getFunction()->name();
+    const TString &name                    = functionCall->getFunction()->name();
     TIntermNode *offset        = nullptr;
     TIntermSequence *arguments = functionCall->getSequence();
     bool useTextureGatherOffsetConstraints = false;
@@ -5628,8 +5624,8 @@
 void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name = *functionCall->getFunction()->name();
-    if (IsAtomicBuiltin(name))
+    const TString &functionName = functionCall->getFunction()->name();
+    if (IsAtomicBuiltin(functionName))
     {
         TIntermSequence *arguments = functionCall->getSequence();
         TIntermTyped *memNode      = (*arguments)[0]->getAsTyped();
@@ -5651,7 +5647,7 @@
         error(memNode->getLine(),
               "The value passed to the mem argument of an atomic memory function does not "
               "correspond to a buffer or shared variable.",
-              functionCall->getFunction()->name()->c_str());
+              functionName.c_str());
     }
 }
 
@@ -5659,7 +5655,7 @@
 void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name = *functionCall->getFunction()->name();
+    const TString &name = functionCall->getFunction()->name();
 
     if (name.compare(0, 5, "image") == 0)
     {
@@ -5775,7 +5771,7 @@
     }
 }
 
-TIntermTyped *TParseContext::addMethod(const TString *name,
+TIntermTyped *TParseContext::addMethod(const TString &name,
                                        TIntermSequence *arguments,
                                        TIntermNode *thisNode,
                                        const TSourceLoc &loc)
@@ -5785,9 +5781,9 @@
     // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
     // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
     // So accessing fnCall->name() below is safe.
-    if (*name != "length")
+    if (name != "length")
     {
-        error(loc, "invalid method", name->c_str());
+        error(loc, "invalid method", name.c_str());
     }
     else if (!arguments->empty())
     {
@@ -5812,27 +5808,26 @@
     return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
 }
 
-TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString *name,
+TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString &name,
                                                            TIntermSequence *arguments,
                                                            const TSourceLoc &loc)
 {
-    ASSERT(name);
     // First find by unmangled name to check whether the function name has been
     // hidden by a variable name or struct typename.
     // If a function is found, check for one with a matching argument list.
     bool builtIn;
-    const TSymbol *symbol = symbolTable.find(*name, mShaderVersion, &builtIn);
+    const TSymbol *symbol = symbolTable.find(name, mShaderVersion, &builtIn);
     if (symbol != nullptr && !symbol->isFunction())
     {
-        error(loc, "function name expected", name->c_str());
+        error(loc, "function name expected", name.c_str());
     }
     else
     {
-        symbol = symbolTable.find(TFunction::GetMangledNameFromCall(*name, *arguments),
+        symbol = symbolTable.find(TFunction::GetMangledNameFromCall(name, *arguments),
                                   mShaderVersion, &builtIn);
         if (symbol == nullptr)
         {
-            error(loc, "no matching overloaded function found", name->c_str());
+            error(loc, "no matching overloaded function found", name.c_str());
         }
         else
         {
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 19c0149..9e713a0 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -549,14 +549,14 @@
                                 const TSourceLoc &loc);
     TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
 
-    TIntermTyped *addMethod(const TString *name,
+    TIntermTyped *addMethod(const TString &name,
                             TIntermSequence *arguments,
                             TIntermNode *thisNode,
                             const TSourceLoc &loc);
     TIntermTyped *addConstructor(TIntermSequence *arguments,
                                  TType type,
                                  const TSourceLoc &line);
-    TIntermTyped *addNonConstructorFunctionCall(const TString *name,
+    TIntermTyped *addNonConstructorFunctionCall(const TString &name,
                                                 TIntermSequence *arguments,
                                                 const TSourceLoc &loc);
 
diff --git a/src/compiler/translator/RegenerateStructNames.cpp b/src/compiler/translator/RegenerateStructNames.cpp
index 32940d8..4f3dda9 100644
--- a/src/compiler/translator/RegenerateStructNames.cpp
+++ b/src/compiler/translator/RegenerateStructNames.cpp
@@ -26,8 +26,6 @@
         return;
     }
 
-    ASSERT(userType->name() != nullptr);
-
     int uniqueId = userType->uniqueId().get();
 
     ASSERT(mScopeDepth > 0);
@@ -53,14 +51,14 @@
         return;
     // Map {name} to _webgl_struct_{uniqueId}_{name}.
     const char kPrefix[] = "_webgl_struct_";
-    if (userType->name()->find(kPrefix) == 0)
+    if (userType->name().find(kPrefix) == 0)
     {
         // The name has already been regenerated.
         return;
     }
     std::string id = Str(uniqueId);
     TString tmp    = kPrefix + TString(id.c_str());
-    tmp += "_" + *userType->name();
+    tmp += "_" + userType->name();
     userType->setName(tmp);
 }
 
diff --git a/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/compiler/translator/RewriteTexelFetchOffset.cpp
index ceb903c..b93d9a1 100644
--- a/src/compiler/translator/RewriteTexelFetchOffset.cpp
+++ b/src/compiler/translator/RewriteTexelFetchOffset.cpp
@@ -72,7 +72,8 @@
         return true;
     }
 
-    if (*node->getFunction()->name() != "texelFetchOffset")
+    ASSERT(node->getFunction()->symbolType() == SymbolType::BuiltIn);
+    if (node->getFunction()->name() != "texelFetchOffset")
     {
         return true;
     }
diff --git a/src/compiler/translator/Symbol.cpp b/src/compiler/translator/Symbol.cpp
index fe5914c..f85e7eb 100644
--- a/src/compiler/translator/Symbol.cpp
+++ b/src/compiler/translator/Symbol.cpp
@@ -38,22 +38,22 @@
            mSymbolType == SymbolType::NotResolved || mSymbolType == SymbolType::Empty);
 }
 
-const TString *TSymbol::name() const
+const TString &TSymbol::name() const
 {
-    if (mName != nullptr || mSymbolType == SymbolType::Empty)
+    if (mName != nullptr)
     {
-        return mName;
+        return *mName;
     }
     ASSERT(mSymbolType == SymbolType::AngleInternal);
     TInfoSinkBase symbolNameOut;
     symbolNameOut << "s" << mUniqueId.get();
-    return NewPoolTString(symbolNameOut.c_str());
+    return *NewPoolTString(symbolNameOut.c_str());
 }
 
 const TString &TSymbol::getMangledName() const
 {
     ASSERT(mSymbolType != SymbolType::Empty);
-    return *name();
+    return name();
 }
 
 TVariable::TVariable(TSymbolTable *symbolTable,
@@ -160,7 +160,7 @@
 
 const TString *TFunction::buildMangledName() const
 {
-    std::string newName = name()->c_str();
+    std::string newName = name().c_str();
     newName += kFunctionMangledNameSeparator;
 
     for (const auto &p : parameters)
@@ -185,13 +185,13 @@
 
 bool TFunction::isMain() const
 {
-    return symbolType() == SymbolType::UserDefined && *name() == "main";
+    return symbolType() == SymbolType::UserDefined && name() == "main";
 }
 
 bool TFunction::isImageFunction() const
 {
     return symbolType() == SymbolType::BuiltIn &&
-           (*name() == "imageSize" || *name() == "imageLoad" || *name() == "imageStore");
+           (name() == "imageSize" || name() == "imageLoad" || name() == "imageStore");
 }
 
 }  // namespace sh
diff --git a/src/compiler/translator/Symbol.h b/src/compiler/translator/Symbol.h
index eba4d38..650a120 100644
--- a/src/compiler/translator/Symbol.h
+++ b/src/compiler/translator/Symbol.h
@@ -43,11 +43,14 @@
         // don't delete name, it's from the pool
     }
 
-    const TString *name() const;
+    // Don't call name() or getMangledName() for empty symbols (symbolType == SymbolType::Empty).
+    const TString &name() const;
     virtual const TString &getMangledName() const;
+
     virtual bool isFunction() const { return false; }
     virtual bool isVariable() const { return false; }
     virtual bool isStruct() const { return false; }
+
     const TSymbolUniqueId &uniqueId() const { return mUniqueId; }
     SymbolType symbolType() const { return mSymbolType; }
     TExtension extension() const { return mExtension; }
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index e25cf37..f7d213b 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -42,8 +42,7 @@
 bool TSymbolTableLevel::insertUnmangled(TFunction *function)
 {
     // returning true means symbol was added to the table
-    ASSERT(function->name() != nullptr);
-    tInsertResult result = level.insert(tLevelPair(*function->name(), function));
+    tInsertResult result = level.insert(tLevelPair(function->name(), function));
 
     return result.second;
 }
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index 3ca8806..867b955 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -475,16 +475,15 @@
         {
             case EbtStruct:
                 mangledName += "struct-";
-                if (mStructure->name() != nullptr)
+                if (mStructure->symbolType() != SymbolType::Empty)
                 {
-                    mangledName += *mStructure->name();
+                    mangledName += mStructure->name();
                 }
                 mangledName += mStructure->mangledFieldList();
                 break;
             case EbtInterfaceBlock:
                 mangledName += "iblock-";
-                ASSERT(mInterfaceBlock->name() != nullptr);
-                mangledName += *mInterfaceBlock->name();
+                mangledName += mInterfaceBlock->name();
                 mangledName += mInterfaceBlock->mangledFieldList();
                 break;
             default:
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
index 079c550..ebea83d 100644
--- a/src/compiler/translator/UniformHLSL.cpp
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -61,8 +61,7 @@
 
 static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
 {
-    ASSERT(interfaceBlock.name() != nullptr);
-    return DecoratePrivate(*interfaceBlock.name()) + "_type";
+    return DecoratePrivate(interfaceBlock.name()) + "_type";
 }
 
 void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out,
@@ -480,8 +479,7 @@
         }
 
         unsigned int activeRegister                             = mUniformBlockRegister;
-        ASSERT(interfaceBlock.name() != nullptr);
-        mUniformBlockRegisterMap[interfaceBlock.name()->c_str()] = activeRegister;
+        mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
 
         if (instanceName != "" && nodeType.isArray())
         {
@@ -512,8 +510,7 @@
 {
     const TString &arrayIndexString =
         (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
-    ASSERT(interfaceBlock.name() != nullptr);
-    const TString &blockName = *interfaceBlock.name() + arrayIndexString;
+    const TString &blockName = interfaceBlock.name() + arrayIndexString;
     TString hlsl;
 
     hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) +
diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp
index 91934c7..9e9bd20 100644
--- a/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/compiler/translator/UtilsHLSL.cpp
@@ -735,15 +735,15 @@
     if (func->symbolType() == SymbolType::AngleInternal)
     {
         // The name should not have a prefix reserved for user-defined variables or functions.
-        ASSERT(func->name()->compare(0, 2, "f_") != 0);
-        ASSERT(func->name()->compare(0, 1, "_") != 0);
-        return *func->name();
+        ASSERT(func->name().compare(0, 2, "f_") != 0);
+        ASSERT(func->name().compare(0, 1, "_") != 0);
+        return func->name();
     }
-    ASSERT(func->name()->compare(0, 3, "gl_") != 0);
+    ASSERT(func->name().compare(0, 3, "gl_") != 0);
     // Add an additional f prefix to functions so that they're always disambiguated from variables.
     // This is necessary in the corner case where a variable declaration hides a function that it
     // uses in its initializer.
-    return "f_" + (*func->name());
+    return "f_" + func->name();
 }
 
 TString TypeString(const TType &type)
@@ -855,10 +855,10 @@
     // translation so that we can link between shader stages.
     if (structure.atGlobalScope())
     {
-        return Decorate(*structure.name());
+        return Decorate(structure.name());
     }
 
-    return "ss" + str(structure.uniqueId().get()) + "_" + *structure.name();
+    return "ss" + str(structure.uniqueId().get()) + "_" + structure.name();
 }
 
 TString QualifiedStructNameString(const TStructure &structure,
diff --git a/src/tests/compiler_tests/InitOutputVariables_test.cpp b/src/tests/compiler_tests/InitOutputVariables_test.cpp
index c59d1a5..3b841cf 100644
--- a/src/tests/compiler_tests/InitOutputVariables_test.cpp
+++ b/src/tests/compiler_tests/InitOutputVariables_test.cpp
@@ -167,8 +167,8 @@
 
         TStructure *structure = symbol->getTypePointer()->getStruct();
 
-        if (structure != nullptr && structure->name() != nullptr &&
-            *structure->name() == mStructName)
+        if (structure != nullptr && structure->symbolType() != SymbolType::Empty &&
+            structure->name() == mStructName)
         {
             mStructure = structure;
         }