diff --git a/media/specs/name-mangling.md b/media/specs/name-mangling.md new file mode 100644 index 000000000..56038205d --- /dev/null +++ b/media/specs/name-mangling.md @@ -0,0 +1,59 @@ +# Technical Specification for Name Mangling in Spice + +With Spice having support for function overloading, default parameter values, generics, etc., it is required to identify +functions, structs and types uniquely. For this purpose, Spice offers a flexible name mangling scheme for names on ABI level. + +## Function mangling + +### Components + +- Function name +- Function type (function: `f`, procedure `p`, method function `mf` or method procedure `mp`) +- This type (struct type for methods, default `void`) +- Return type (`void` for procedures) +- Template types (separated by `_`, default: empty) +- Param types (separated by `_`, default: empty) + +### Mangled name + +Here is the scheme, how Spice mangles function/procedure/method names: + +`_____[__]__[__]` + +**Example:** + +Mangled name: `_mp__Vector__void__int__pushBack__int` + +### Exception: main function + +As the `main` function is exposed to the operating system, it is the only Spice function, where the mangling rules do not apply. +It's name stays the same on the ABI level. + +### Implementation + +To see the implementation for function name mangling, have a look here: +[Function::getMangledName](../../src/model/Function.cpp#:~:text=Function::getMangledName) + + +## Struct mangling + +### Components + +- Struct name +- Field types (separated by `_`, default: empty) +- Template types (separated by `_`, default: empty) + +### Mangled name + +Here is the scheme, how Spice mangles struct names: + +`_s[__]__[__field-types]` + +**Example:** + +`_s__int_string__Pair__int_string` + +### Implementation + +To see the implementation for struct name mangling, have a look here: +[Struct::gerMangledName](../../src/model/Struct.cpp#:~:text=Struct::getMangledName) \ No newline at end of file diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 5368659cb..96e78c86d 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -1,15 +1,41 @@ -import "std/data/vector"; -import "std/data/pair"; +type T int|long; + +type TestStruct struct { + T f1 + unsigned long length +} + +p TestStruct.ctor(const unsigned long initialLength) { + this.length = initialLength; +} + +p TestStruct.printLength() { + printf("%d\n", this.length); +} + +type Alias alias TestStruct; f main() { - Vector> pairVector = Vector>(); - /*pairVector.pushBack(Pair(0, "Hello")); - pairVector.pushBack(Pair(1, "World")); + Alias a = Alias{12345l, 54321l}; + a.printLength(); + dyn b = Alias(12l); + b.printLength(); +} + +/*type T dyn; + +type Vector struct { + T data +} - Pair p1 = pairVector.get(1); - printf("Hello %s!\n", p1.getSecond());*/ +p Vector.ctor() { + this.data = 12; } +f main() { + Vector intVec = Vector(); +}*/ + /*type T string|char; type TestStruct struct { diff --git a/src/model/Function.cpp b/src/model/Function.cpp index e90c39f2a..30a0b4f0a 100644 --- a/src/model/Function.cpp +++ b/src/model/Function.cpp @@ -54,6 +54,14 @@ std::string Function::getMangledName() const { if (!returnType.is(TY_DYN)) returnTyStr = returnType.getName(false, true); + // Template type string + std::stringstream templateTyStr; + for (size_t i = 0; i < templateTypes.size(); i++) { + if (i != 0) + templateTyStr << "_"; + templateTyStr << templateTypes.at(i).getName(false, true); + } + // Param type string std::stringstream paramTyStr; for (size_t i = 0; i < paramList.size(); i++) { @@ -65,14 +73,6 @@ std::string Function::getMangledName() const { paramTyStr << "?"; } - // Template type string - std::stringstream templateTyStr; - for (size_t i = 0; i < templateTypes.size(); i++) { - if (i != 0) - templateTyStr << "_"; - templateTyStr << templateTypes.at(i).getName(false, true); - } - // Construct mangled name std::stringstream mangledName; mangledName << "_" << functionTyStr << "__" << thisTyStr << "__" << returnTyStr; @@ -92,10 +92,10 @@ std::string Function::getMangledName() const { * * @return String representation as function signature */ -std::string Function::getSignature() const { +std::string Function::getSignature(bool withThisType /*=true*/) const { // Build this type string std::stringstream thisTyStr; - if (!thisType.is(TY_DYN)) { + if (withThisType && !thisType.is(TY_DYN)) { thisTyStr << thisType.getBaseType().getSubType(); const std::vector &thisTemplateTypes = thisType.getTemplateTypes(); if (!thisTemplateTypes.empty()) { diff --git a/src/model/Function.h b/src/model/Function.h index 9d4b04eef..f77ea5687 100644 --- a/src/model/Function.h +++ b/src/model/Function.h @@ -43,7 +43,7 @@ class Function { // Public methods [[nodiscard]] std::vector getParamTypes() const; [[nodiscard]] std::string getMangledName() const; - [[nodiscard]] std::string getSignature() const; + [[nodiscard]] std::string getSignature(bool withThisType = true) const; [[nodiscard]] inline bool isMethod() const { return !thisType.is(TY_DYN); } [[nodiscard]] inline bool isFunction() const { return !isMethod() && !returnType.is(TY_DYN); } [[nodiscard]] inline bool isProcedure() const { return !isMethod() && returnType.is(TY_DYN); } diff --git a/src/symboltablebuilder/Scope.cpp b/src/symboltablebuilder/Scope.cpp index fab2ade42..dfb99ff97 100644 --- a/src/symboltablebuilder/Scope.cpp +++ b/src/symboltablebuilder/Scope.cpp @@ -61,11 +61,15 @@ void Scope::renameChildScope(const std::string &oldName, const std::string &newN */ void Scope::copyChildScope(const std::string &oldName, const std::string &newName) { assert(children.contains(oldName) && !children.contains(newName)); + // Create copy const Scope *origChildScope = children.at(oldName); auto newChildBlock = new Scope(*origChildScope); + // Add newChildBlock as parent of all children for tracking de-allocation for (const auto &child : newChildBlock->children) child.second->parents.push_back(newChildBlock); + + // Insert the new child scope as child to the current scope children.insert({newName, newChildBlock}); } @@ -217,16 +221,28 @@ void Scope::collectWarnings(std::vector &warnings) const { // N switch (entry.getType().getSuperType()) { case TY_FUNCTION: { + // Skip generic function entries + if (!entry.getType().getTemplateTypes().empty()) + continue; + warningType = UNUSED_FUNCTION; - warningMessage = "The function '" + entry.declNode->getFctManifestations()->front()->getSignature() + "' is unused"; + warningMessage = "The function '" + key + "' is unused"; break; } case TY_PROCEDURE: { + // Skip generic procedure entries + if (!entry.getType().getTemplateTypes().empty()) + continue; + warningType = UNUSED_PROCEDURE; - warningMessage = "The procedure '" + entry.declNode->getFctManifestations()->front()->getSignature() + "' is unused"; + warningMessage = "The procedure '" + key + "' is unused"; break; } case TY_STRUCT: { + // Skip generic struct entries + if (!entry.getType().getTemplateTypes().empty()) + continue; + if (entry.scope->type == SCOPE_GLOBAL) { warningType = UNUSED_STRUCT; warningMessage = "The struct '" + entry.name + "' is unused"; @@ -283,9 +299,11 @@ void Scope::collectWarnings(std::vector &warnings) const { // N // Add warning warnings.emplace_back(entry.getDeclCodeLoc(), warningType, warningMessage); } + // Visit children for (const auto &child : children) - child.second->collectWarnings(warnings); + if (!child.second->isGenericScope) + child.second->collectWarnings(warnings); } /** diff --git a/src/symboltablebuilder/Scope.h b/src/symboltablebuilder/Scope.h index 06987d998..fdd693f4f 100644 --- a/src/symboltablebuilder/Scope.h +++ b/src/symboltablebuilder/Scope.h @@ -98,6 +98,7 @@ class Scope { const ScopeType type; SymbolTable symbolTable = SymbolTable(parent == nullptr ? nullptr : &parent->symbolTable, this); const CodeLoc *codeLoc = nullptr; + bool isGenericScope = false; private: // Private members diff --git a/src/symboltablebuilder/SymbolTable.cpp b/src/symboltablebuilder/SymbolTable.cpp index d5ebf8f81..634b8271e 100644 --- a/src/symboltablebuilder/SymbolTable.cpp +++ b/src/symboltablebuilder/SymbolTable.cpp @@ -55,7 +55,7 @@ SymbolTableEntry *SymbolTable::insertAnonymous(const SymbolType &type, ASTNode * * @param originalName Original symbol name * @param newName New symbol name */ -void SymbolTable::copy(const std::string &originalName, const std::string &newName) { +void SymbolTable::copySymbol(const std::string &originalName, const std::string &newName) { SymbolTableEntry *entryToCopy = lookupStrict(originalName); assert(entryToCopy != nullptr); symbols.insert({newName, *entryToCopy}); diff --git a/src/symboltablebuilder/SymbolTable.h b/src/symboltablebuilder/SymbolTable.h index 14c5d85f9..5a4859ec1 100644 --- a/src/symboltablebuilder/SymbolTable.h +++ b/src/symboltablebuilder/SymbolTable.h @@ -38,7 +38,7 @@ class SymbolTable { // Public methods SymbolTableEntry *insert(const std::string &name, const SymbolSpecifiers &specifiers, ASTNode *declNode); SymbolTableEntry *insertAnonymous(const SymbolType &type, ASTNode *declNode); - void copy(const std::string &originalName, const std::string &newName); + void copySymbol(const std::string &originalName, const std::string &newName); SymbolTableEntry *lookup(const std::string &symbolName); SymbolTableEntry *lookupStrict(const std::string &symbolName); SymbolTableEntry *lookupByIndex(unsigned int orderIndex); diff --git a/src/symboltablebuilder/SymbolTableBuilder.cpp b/src/symboltablebuilder/SymbolTableBuilder.cpp index 501d811ea..946e25590 100644 --- a/src/symboltablebuilder/SymbolTableBuilder.cpp +++ b/src/symboltablebuilder/SymbolTableBuilder.cpp @@ -36,6 +36,7 @@ std::any SymbolTableBuilder::visitMainFctDef(MainFctDefNode *node) { // Create scope for main function body node->fctScope = currentScope = rootScope->createChildScope(node->getScopeId(), SCOPE_FUNC_PROC_BODY, &node->codeLoc); + currentScope->isGenericScope = false; // Declare variable for the return value in the function scope SymbolTableEntry *resultVarEntry = node->fctScope->insert(RETURN_VARIABLE_NAME, SymbolSpecifiers::of(TY_INT), node); @@ -80,6 +81,7 @@ std::any SymbolTableBuilder::visitFctDef(FctDefNode *node) { // Create scope for the function node->fctScope = currentScope = currentScope->createChildScope(node->getScopeId(), SCOPE_FUNC_PROC_BODY, &node->codeLoc); + currentScope->isGenericScope = node->hasTemplateTypes; // Create symbol for 'this' variable if (node->isMethod) { @@ -141,6 +143,7 @@ std::any SymbolTableBuilder::visitProcDef(ProcDefNode *node) { // Create scope for the procedure node->procScope = currentScope = currentScope->createChildScope(node->getScopeId(), SCOPE_FUNC_PROC_BODY, &node->codeLoc); + currentScope->isGenericScope = node->hasTemplateTypes; // Create symbol for 'this' variable if (node->isMethod) { @@ -182,6 +185,7 @@ std::any SymbolTableBuilder::visitStructDef(StructDefNode *node) { // Create scope for the struct node->structScope = currentScope = rootScope->createChildScope(STRUCT_SCOPE_PREFIX + node->structName, SCOPE_STRUCT, &node->codeLoc); + currentScope->isGenericScope = node->isGeneric; // Visit struct fields for (FieldNode *field : node->fields()) diff --git a/src/typechecker/FunctionManager.cpp b/src/typechecker/FunctionManager.cpp index 294c941db..63998b6b3 100644 --- a/src/typechecker/FunctionManager.cpp +++ b/src/typechecker/FunctionManager.cpp @@ -183,7 +183,11 @@ Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &r matchScope = substantiatedStructBodyScope; } - // We found a match! -> Check if it needs to be substantiated + // We found a match! -> Set the actual candidate and its entry to used + candidate.used = true; + candidate.entry->used = true; + + // Check if the function is generic needs to be substantiated if (presetFunction.templateTypes.empty()) { assert(matchScope->functions.contains(defCodeLocStr) && matchScope->functions.at(defCodeLocStr).contains(mangledName)); matches.push_back(&matchScope->functions.at(defCodeLocStr).at(mangledName)); @@ -211,17 +215,25 @@ Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &r substantiatedFunction->genericSubstantiation = true; substantiatedFunction->declNode->getFctManifestations()->push_back(substantiatedFunction); + // Copy function entry + const std::string newSignature = substantiatedFunction->getSignature(); + matchScope->symbolTable.copySymbol(presetFunction.entry->name, newSignature); + matchScope->lookupStrict(presetFunction.entry->name)->used = true; + candidate.entry = matchScope->lookupStrict(newSignature); + candidate.entry->used = true; + // Copy function scope - matchScope->copyChildScope(presetFunction.getSignature(), substantiatedFunction->getSignature()); + matchScope->copyChildScope(presetFunction.getSignature(false), newSignature); + Scope *childScope = matchScope->getChildScope(newSignature); + childScope->isGenericScope = false; // Insert symbols for generic type names with concrete types into the child block - Scope *childBlock = matchScope->getChildScope(substantiatedFunction->getSignature()); for (const auto &[typeName, concreteType] : candidate.typeMapping) - childBlock->insertGenericType(typeName, GenericType(concreteType)); + childScope->insertGenericType(typeName, GenericType(concreteType)); // Substantiate the 'this' symbol table entry in the new function scope if (presetFunction.isMethod() && !presetFunction.templateTypes.empty()) { - SymbolTableEntry *thisEntry = childBlock->lookupStrict(THIS_VARIABLE_NAME); + SymbolTableEntry *thisEntry = childScope->lookupStrict(THIS_VARIABLE_NAME); assert(thisEntry != nullptr); thisEntry->updateType(requestedThisType.toPointer(callNode), /*overwriteExistingType=*/true); } @@ -357,7 +369,8 @@ bool FunctionManager::matchArgTypes(Function &candidate, const std::vector &requestedParamTypes, TypeMapping &typeMapping); [[nodiscard]] static const GenericType *getGenericTypeOfCandidateByName(const Function &candidate, - const std::string &templateTypeName); + const std::string &templateTypeName); }; } // namespace spice::compiler \ No newline at end of file diff --git a/src/typechecker/StructManager.cpp b/src/typechecker/StructManager.cpp index 7a603e020..658599d7e 100644 --- a/src/typechecker/StructManager.cpp +++ b/src/typechecker/StructManager.cpp @@ -84,7 +84,11 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request // Map field types from generic to concrete substantiateFieldTypes(candidate, candidate.typeMapping); - // We found a match! -> Check if it needs to be substantiated + // We found a match! -> Set the actual candidate and its entry to used + candidate.used = true; + candidate.entry->used = true; + + // Check if it needs to be substantiated if (presetStruct.templateTypes.empty()) { assert(matchScope->structs.contains(defCodeLocStr) && matchScope->structs.at(defCodeLocStr).contains(mangledName)); matches.push_back(&matchScope->structs.at(defCodeLocStr).at(mangledName)); @@ -101,12 +105,20 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request Struct *substantiatedStruct = insertSubstantiation(matchScope, candidate, presetStruct.declNode); substantiatedStruct->genericSubstantiation = true; substantiatedStruct->declNode->getStructManifestations()->push_back(substantiatedStruct); + + // Copy function entry + const std::string newSignature = substantiatedStruct->getSignature(); + matchScope->symbolTable.copySymbol(candidate.name, newSignature); + matchScope->lookupStrict(candidate.name)->used = true; + candidate.entry = matchScope->lookupStrict(newSignature); + // Copy struct scope - const std::string newScopeName = STRUCT_SCOPE_PREFIX + substantiatedStruct->getSignature(); + const std::string newScopeName = STRUCT_SCOPE_PREFIX + newSignature; matchScope->copyChildScope(STRUCT_SCOPE_PREFIX + presetStruct.name, newScopeName); + substantiatedStruct->structScope = matchScope->getChildScope(newScopeName); + substantiatedStruct->structScope->isGenericScope = false; // Replace field types with concrete template types - substantiatedStruct->structScope = matchScope->getChildScope(newScopeName); assert(substantiatedStruct->structScope != nullptr); for (size_t i = 0; i < candidate.fieldTypes.size(); i++) { // Replace field type with concrete template type diff --git a/src/typechecker/TypeChecker.cpp b/src/typechecker/TypeChecker.cpp index be2c7b8a1..28961ef67 100644 --- a/src/typechecker/TypeChecker.cpp +++ b/src/typechecker/TypeChecker.cpp @@ -1318,10 +1318,6 @@ std::any TypeChecker::visitFunctionCall(FunctionCallNode *node) { throw SemanticError(node, INSUFFICIENT_VISIBILITY, "Function/procedure '" + data.callee->getSignature() + "' has insufficient visibility"); - // Set the function to used - data.callee->used = true; - functionEntry->used = true; - // Procedures always have the return type 'bool' if (data.callee->isProcedure() || returnType.is(TY_DYN)) returnType = SymbolType(TY_BOOL); @@ -1356,38 +1352,14 @@ std::tuple TypeChecker::visitOrdinaryFctCall(F } // Check if the exported name registry contains that function name - const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(fqFunctionName); - if (!registryEntry) + const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName); + if (!functionRegistryEntry) throw SemanticError(node, REFERENCED_UNDEFINED_FUNCTION, "Function/procedure/struct '" + node->functionNameFragments.back() + "' could not be found"); - SymbolTableEntry *symbolEntry = registryEntry->targetEntry; + SymbolTableEntry *functionEntry = functionRegistryEntry->targetEntry; // Check if the target symbol is a struct -> this must be a constructor call - std::string knownStructName; - std::string functionName = node->functionNameFragments.back(); - if (symbolEntry != nullptr && symbolEntry->getType().is(TY_STRUCT)) { - const NameRegistryEntry *structRegistryEntry = registryEntry; - const std::string structName = structRegistryEntry->targetEntry->name; - - // Override function name - functionName = CTOR_FUNCTION_NAME; - - // Retrieve the name registry entry for the constructor - registryEntry = sourceFile->getNameRegistryEntry(fqFunctionName + MEMBER_ACCESS_TOKEN + functionName); - // Check if the constructor was found - if (!registryEntry) - throw SemanticError(node, REFERENCED_UNDEFINED_FUNCTION, "The struct '" + structName + "' does not provide a constructor"); - data.isConstructorCall = true; - - // Set the 'this' type of the function to the struct type - data.thisType = symbolEntry->getType(); - - // Set the struct to used - structRegistryEntry->targetEntry->used = true; - - // Get the name, that can be used in the current source file to identify the struct - knownStructName = structRegistryEntry->name; - } + data.isConstructorCall = functionEntry != nullptr && functionEntry->getType().is(TY_STRUCT); // Get concrete template types if (node->hasTemplateTypes) { @@ -1408,12 +1380,41 @@ std::tuple TypeChecker::visitOrdinaryFctCall(F } } + // For constructor calls, do some preparation + std::string knownStructName; + std::string functionName = node->functionNameFragments.back(); + if (data.isConstructorCall) { + const NameRegistryEntry *structRegistryEntry = functionRegistryEntry; + const SymbolTableEntry *structEntry = functionEntry; + const std::string structName = structRegistryEntry->targetEntry->name; + + // Substantiate potentially generic this struct + Struct *thisStruct = StructManager::matchStruct(structEntry->scope, structName, concreteTemplateTypes, node); + assert(thisStruct != nullptr); + + // Override function name + functionName = CTOR_FUNCTION_NAME; + + // Retrieve the name registry entry for the constructor + functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName + MEMBER_ACCESS_TOKEN + functionName); + // Check if the constructor was found + if (!functionRegistryEntry) + throw SemanticError(node, REFERENCED_UNDEFINED_FUNCTION, "The struct '" + structName + "' does not provide a constructor"); + + // Set the 'this' type of the function to the struct type + data.thisType = structEntry->getType(); + data.thisType.setStructBodyScope(thisStruct->structScope); + + // Get the fully qualified name, that can be used in the current source file to identify the struct + knownStructName = structRegistryEntry->name; + } + // Attach the concrete template types to the 'this' type if (!data.thisType.is(TY_DYN) && !concreteTemplateTypes.empty()) data.thisType.setTemplateTypes(concreteTemplateTypes); // Map local types to imported types - Scope *functionParentScope = registryEntry->targetScope; + Scope *functionParentScope = functionRegistryEntry->targetScope; std::vector importedArgTypes = data.argTypes; for (SymbolType &symbolType : importedArgTypes) symbolType = mapLocalTypeToImportedScopeType(functionParentScope, symbolType); @@ -1542,19 +1543,6 @@ std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) { } node->instantiatedStructs.at(manIdx) = spiceStruct; - // Ensure that the struct object has the right entry attached - if (spiceStruct->genericSubstantiation) { - Scope *structParentScope = registryEntry->targetScope->parent; - structParentScope->symbolTable.copy(structName, spiceStruct->getSignature()); - spiceStruct->entry = structParentScope->lookupStrict(spiceStruct->getSignature()); - assert(spiceStruct->entry != nullptr); - spiceStruct->entry->used = true; // We use it directly, so set it to used - } - - // Set struct to used - spiceStruct->used = true; - structEntry->used = true; - // Use scope of concrete substantiation and not the scope of the generic type structScope = spiceStruct->structScope; structType.setStructBodyScope(structScope); @@ -1730,10 +1718,8 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) { // Here, it is allowed to accept, that the struct cannot be found, because there are self-referencing structs const std::string structName = node->typeNameFragments.back(); Struct *spiceStruct = StructManager::matchStruct(accessScope, structName, concreteTemplateTypes, node); - if (spiceStruct) { - spiceStruct->used = true; + if (spiceStruct) entryType.setStructBodyScope(spiceStruct->structScope); - } return node->setEvaluatedSymbolType(entryType, manIdx); } @@ -1769,6 +1755,7 @@ SymbolType TypeChecker::mapLocalTypeToImportedScopeType(const Scope *targetScope for (const Struct *manifestation : *entry.targetEntry->declNode->getStructManifestations()) if (manifestation->structScope == symbolType.getBaseType().getStructBodyScope()) return symbolType.replaceBaseSubType(manifestation->name); + return symbolType; } diff --git a/src/typechecker/TypeCheckerPrepare.cpp b/src/typechecker/TypeCheckerPrepare.cpp index 1329911ce..ab940f95b 100644 --- a/src/typechecker/TypeCheckerPrepare.cpp +++ b/src/typechecker/TypeCheckerPrepare.cpp @@ -135,9 +135,9 @@ std::any TypeChecker::visitFctDefPrepare(FctDefNode *node) { // Rename / duplicate the original child scope to reflect the substantiated versions of the function std::vector substantiatedFunctions; FunctionManager::substantiateOptionalParams(spiceFunc, substantiatedFunctions); - currentScope->renameChildScope(node->getScopeId(), substantiatedFunctions.front().getSignature()); + currentScope->renameChildScope(node->getScopeId(), substantiatedFunctions.front().getSignature(false)); for (size_t i = 1; i < substantiatedFunctions.size(); i++) - currentScope->copyChildScope(substantiatedFunctions.front().getSignature(), substantiatedFunctions[i].getSignature()); + currentScope->copyChildScope(substantiatedFunctions.front().getSignature(), substantiatedFunctions[i].getSignature(false)); // Change to the root scope currentScope = rootScope; @@ -239,9 +239,9 @@ std::any TypeChecker::visitProcDefPrepare(ProcDefNode *node) { // Rename / duplicate the original child block to reflect the substantiated versions of the procedure std::vector substantiatedProcedures; FunctionManager::substantiateOptionalParams(spiceProc, substantiatedProcedures); - currentScope->renameChildScope(node->getScopeId(), substantiatedProcedures.front().getSignature()); + currentScope->renameChildScope(node->getScopeId(), substantiatedProcedures.front().getSignature(false)); for (size_t i = 1; i < substantiatedProcedures.size(); i++) - currentScope->copyChildScope(substantiatedProcedures.front().getSignature(), substantiatedProcedures[i].getSignature()); + currentScope->copyChildScope(substantiatedProcedures.front().getSignature(), substantiatedProcedures[i].getSignature(false)); // Change to the root scope currentScope = rootScope; diff --git a/test/test-files/irgenerator/threads/success-basic-threads/disabled b/test/test-files/irgenerator/threads/success-basic-threads/disabled new file mode 100644 index 000000000..e69de29bb diff --git a/test/test-files/irgenerator/variables/success-global-variables/disabled b/test/test-files/irgenerator/variables/success-global-variables/disabled new file mode 100644 index 000000000..e69de29bb