Always create TFunctions for function call nodes

This simplifies code and ensures that nodes get consistent data.

In the future function call nodes could have a pointer to the
TFunction instead of converting the same information into a different
data structure.

BUG=angleproject:2267
TEST=angle_unittests, angle_end2end_tests

Change-Id: Ic0c24bb86b44b9bcc4a5da7f6b03701081a3af5c
Reviewed-on: https://chromium-review.googlesource.com/824606
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index a2b486d..1ead5a5 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1682,7 +1682,7 @@
             {
                 error(argument->getLine(),
                       "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
-                      fnCall->getFunctionSymbolInfo()->getName().c_str());
+                      fnCall->functionName());
                 return;
             }
         }
@@ -1692,7 +1692,7 @@
             {
                 error(argument->getLine(),
                       "Constant value cannot be passed for 'out' or 'inout' parameters.",
-                      fnCall->getFunctionSymbolInfo()->getName().c_str());
+                      fnCall->functionName());
                 return;
             }
         }
@@ -3442,7 +3442,7 @@
     }
 
     // Add the function as a prototype after parsing it (we do not support recursion)
-    return new TFunction(&symbolTable, name, new TType(type), SymbolType::UserDefined);
+    return new TFunction(&symbolTable, name, new TType(type), SymbolType::UserDefined, false);
 }
 
 TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
@@ -3454,7 +3454,7 @@
     // would be enough, but TFunction carries a lot of extra information in addition to that.
     // Besides function calls we do have to store constructor calls in the same data structure, for
     // them we need to store a TType.
-    return new TFunction(&symbolTable, name, returnType, SymbolType::NotResolved);
+    return new TFunction(&symbolTable, name, returnType, SymbolType::NotResolved, false);
 }
 
 TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
@@ -3478,7 +3478,7 @@
         type->setBasicType(EbtFloat);
     }
 
-    return new TFunction(&symbolTable, nullptr, type, SymbolType::NotResolved, EOpConstruct);
+    return new TFunction(&symbolTable, nullptr, type, SymbolType::NotResolved, true, EOpConstruct);
 }
 
 void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
@@ -5757,7 +5757,7 @@
 {
     if (thisNode != nullptr)
     {
-        return addMethod(fnCall, arguments, thisNode, loc);
+        return addMethod(fnCall->name(), arguments, thisNode, loc);
     }
 
     TOperator op = fnCall->getBuiltInOp();
@@ -5768,11 +5768,11 @@
     else
     {
         ASSERT(op == EOpNull);
-        return addNonConstructorFunctionCall(fnCall, arguments, loc);
+        return addNonConstructorFunctionCall(fnCall->name(), arguments, loc);
     }
 }
 
-TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
+TIntermTyped *TParseContext::addMethod(const TString *name,
                                        TIntermSequence *arguments,
                                        TIntermNode *thisNode,
                                        const TSourceLoc &loc)
@@ -5782,9 +5782,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 (*fnCall->name() != "length")
+    if (*name != "length")
     {
-        error(loc, "invalid method", fnCall->name()->c_str());
+        error(loc, "invalid method", name->c_str());
     }
     else if (!arguments->empty())
     {
@@ -5809,26 +5809,27 @@
     return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
 }
 
-TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
+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(*fnCall->name(), mShaderVersion, &builtIn);
+    const TSymbol *symbol = symbolTable.find(*name, mShaderVersion, &builtIn);
     if (symbol != nullptr && !symbol->isFunction())
     {
-        error(loc, "function name expected", fnCall->name()->c_str());
+        error(loc, "function name expected", name->c_str());
     }
     else
     {
-        symbol = symbolTable.find(TFunction::GetMangledNameFromCall(*fnCall->name(), *arguments),
+        symbol = symbolTable.find(TFunction::GetMangledNameFromCall(*name, *arguments),
                                   mShaderVersion, &builtIn);
         if (symbol == nullptr)
         {
-            error(loc, "no matching overloaded function found", fnCall->name()->c_str());
+            error(loc, "no matching overloaded function found", name->c_str());
         }
         else
         {