--- a/cmajor++/Cm/Cm.Core/Function.cpp
+++ b/cmajor++/Cm/Cm.Core/Function.cpp
@@ -41,32 +41,38 @@
 using Soul::Util::IntToString;
 using Soul::Util::Replace;
 
+bool CompilingForCodeGen()
+{
+    return !ArchetypeInstantiation() && !ConstraintTypeChecking() && !EnumExprCheck() && !ConstantExprCheck() && !GeneratingLibraryDeclarations();
+}
+
 const char* exceptionCodeVarName = "$ex";
 
-int functionCompileLevel = 0;
+int compileLevel = 0;
 
 class FunctionCompileDebugger
 {
 public:
-    FunctionCompileDebugger(bool isFreeFunction, const std::string& functionName_): debugging(false), functionName(functionName_)
-    {
-        if (isFreeFunction && (GetFlags() & Flags::debugCompilingFunctions) != Flags::none)
+    FunctionCompileDebugger(bool isTemplate, bool isFreeFunction_, const std::string& functionName_): debugging(false), id(isTemplate ? "FT" : isFreeFunction_ ? "F" : "M"), functionName(functionName_)
+    {
+        if ((GetFlags() & Flags::debugCompilingFunctions) != Flags::none)
         {
             debugging = true;
-            ++functionCompileLevel;
-            std::cout << "F" + std::string(functionCompileLevel, '>') + " " << functionName << std::endl;
+            std::cout << id << '>' << std::string(compileLevel, '.') << " " << functionName << std::endl;
+            ++compileLevel;
         }
     }
     ~FunctionCompileDebugger()
     {
         if (debugging)
         {
-            std::cout << "F" + std::string(functionCompileLevel, '<') + " " << functionName << std::endl;
-            --functionCompileLevel;
+            --compileLevel;
+            std::cout << id << '<' << std::string(compileLevel, '.') << " " << functionName << std::endl;
         }
     }
 private:
     bool debugging;
+    const char* id;
     std::string functionName;
 };
 
@@ -85,9 +91,14 @@
     Object::SetFunction(this);
 }
 
-void Function::SetCompilationUnit(CompilationUnitPtr compilationUnit)
-{
-    Object::SetCompilationUnit(compilationUnit);
+void Function::SetCompilationUnit(CompilationUnitPtr compilationUnit_)
+{
+    compilationUnit = compilationUnit_;
+}
+
+void Function::SetCompilationUnitInstantiatedFrom(CompilationUnitPtr compilationUnitInstantiatedFrom_)
+{
+    compilationUnitInstantiatedFrom = compilationUnitInstantiatedFrom_;
 }
 
 void Function::Dispose()
@@ -174,6 +185,7 @@
             memFunConvCtor->Dispose();
             memFunConvCtor.reset();
         }
+        externalCompilationUnits.clear();
     }
 }
 
@@ -228,6 +240,9 @@
 
 void Function::SetMangledName()
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     if (IsStaticConstructor())
     {
         StaticConstructorPtr sc = std::static_pointer_cast<StaticConstructor>(shared_from_this());
@@ -235,7 +250,7 @@
     }
     else if (IsStatic())
     {
-        CM_CORE_ASSERT(IsMemberFunction());
+        CM_CORE_ASSERT(IsMemberFunction(), fullName);
         MemberFunctionPtr memFun = std::static_pointer_cast<MemberFunction>(shared_from_this());
         mangledName = MakeAssemblyName(memFun->GetClassType()->FullName()) + "." + MangleName("", functionSetName, ExpressionList(), parameters);
     }
@@ -315,8 +330,12 @@
 
 void Function::TypeCheckSignature(TypeCheckContext& context)
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     if (!IsMember() && context.DeferTypeChecking())
     {
+        context.DeferTypeCheckingFor(shared_from_this());
         SetTypeCheckingPhase(TypeCheckingPhase::not_typechecked);
         return;
     }
@@ -396,7 +415,7 @@
     if (IsGenerated())
     {
         context.PushExtent(TypeCheckExtent::body);
-        CM_CORE_ASSERT(Body());
+        CM_CORE_ASSERT(Body(), fullName);
         Body()->SetFunction(this);
         Body()->TypeCheck(context);
         context.PopExtent();
@@ -444,10 +463,6 @@
     }
     if (IsMember())
     {
-        if (EnclosingScope()->GetFunction(Name(), Lookup::this_scope, Pos()))
-        {
-            context.SetFunctionExists(true);
-        }
         EnclosingScope()->SetObject(shared_from_this()); 
     }
     if (body)
@@ -473,7 +488,9 @@
 void Function::TypeCheckBody(TypeCheckContext& context)
 {
     Object::TypeCheckBody(context);
-    FunctionCompileDebugger compileDebugger(!IsMember(), FullName());
+    bool typeCheckConstrainedTemplate = !constrainedTemplateTypeChecked && IsTemplate() && IsConstrained() && !IsFunctionTemplateReference() && !GetLibrary() && !context.NoConstrainedTemplateTypeChecking();
+    if (IsTemplate() && !typeCheckConstrainedTemplate) return;
+    FunctionCompileDebugger compileDebugger(IsTemplate(), !IsMember(), FullName());
     if (constraint && !IsTemplate() && !context.DontTypeCheckConstraints())
     {
         context.SetOwnerFunction(this);
@@ -481,13 +498,10 @@
         constraint->TypeCheck(context);
         PopConstraintTypeChecking();
     }
-    if (IsTemplate() && IsConstrained() && !IsFunctionTemplateReference() && !context.NoConstrainedTemplateTypeChecking())
-    {
-        if (!constrainedTemplateTypeChecked)
-        {
-            constrainedTemplateTypeChecked = true;
-            TypeCheckConstrainedTemplate();
-        }
+    if (typeCheckConstrainedTemplate)
+    {
+        constrainedTemplateTypeChecked = true;
+        TypeCheckConstrainedTemplate();
         return;
     }
     if (IsTemplate() && !context.TypeCheckTemplates())
@@ -503,21 +517,14 @@
             exceptionCodeVariable->TypeCheck(context);
             exceptionCodeVariable->AddToScope(false);
         }
-        bool dontDeduceNothrow = false;
         FunctionCallPtr staticCtorCall = GetStaticConstructorCall();
         if (staticCtorCall)
         {
             staticCtorCall->TypeCheck(context);
             DestructionStackPtr destructionStack(new DestructionStack());
             staticCtorCall->GenerateDestructionStatements(destructionStack);
-            if (staticCtorCall->GetFunction()->CanThrow())
-            {
-                dontDeduceNothrow = true;
-            }
-        }
-        context.PushDontDeduceNothrow(dontDeduceNothrow);
+        }
         body->TypeCheck(context);
-        context.PopDontDeduceNothrow();
         if (!IsBuiltIn() && ReturnsValue())
         {
             if (!body->AllPathsReturn())
@@ -605,8 +612,11 @@
 
 ObjectPtr Function::Instantiate(ExpressionList& templateArguments, TypeCheckContext& context)
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     int n = templateArguments.size();
-    CM_CORE_ASSERT(n == templateParameters.size());
+    CM_CORE_ASSERT(n == templateParameters.size(), fullName);
     for (int i = 0; i < n; ++i)
     {
         ObjectPtr& templateArg = templateArguments[i];
@@ -639,24 +649,51 @@
     }
     cloneContext.PopCurrentScope();
     instance->instantiatedFromTemplate = true;
+    instance->SetInstantiationStatus(InstantiationStatus::instantiated);
     instance->AddImportScopes(ImportScopes());
     instance->SetTemplateArguments(templateArguments);
     instance->SetLibrary(GetLibrary());
     instance->SetName(MakeTemplateInstanceName(instance, instance->TemplateArguments(), false, context));
+    if (CompilingForCodeGen())
+    {
+        if (context.GetExtent() == TypeCheckExtent::body)
+        {
+            FunctionPtr prev = GetFunctionTemplateFromGlobalTemplateRepository(instance->FullName());
+            if (prev)
+            {
+                return prev;
+            }
+        }        
+    }
+    else 
+    {
+        ObjectPtr prev = GetArchetypeFromRepository(instance->FullName());
+        if (prev)
+        {
+            return prev;
+        }
+    }
     if (context.GetExtent() == TypeCheckExtent::body)
     {
-        FunctionPtr prev = GetFunctionTemplateFromGlobalTemplateRepository(instance->FullName());
-        if (prev)
-        {
-            return prev;
-        }
-    }
-    if (context.GetExtent() == TypeCheckExtent::body)
-    {
-        PutFunctionTemplateToGlobalTemplateRepository(instance);
+        if (CompilingForCodeGen())
+        {
+            PutFunctionTemplateToGlobalTemplateRepository(instance);
+            CompilationUnitPtr compilationUnit = GetCompilationUnit();
+            CM_CORE_ASSERT(compilationUnit, fullName);
+            instance->SetCompilationUnitInstantiatedFrom(compilationUnit);
+        }
+        else
+        {
+            PutArchetypeToRepository(instance);
+        }
+    }
+    if (context.GetExtent() == TypeCheckExtent::body && CompilingForCodeGen())
+    {
         CompilationUnitPtr compilationUnit = GetCompilationUnit();
-        CM_CORE_ASSERT(compilationUnit);
-        instance->SetCompilationUnitInstantiatedFrom(compilationUnit);
+        ProjectPtr project = compilationUnit->GetProject();
+        CM_CORE_ASSERT(project, fullName);
+        TemplateRepositoryPtr templateRepository = project->GetTemplateRepository();
+        templateRepository->AddInstantiatedTemplate(instance);
     }
     if (!context.DontTypeCheckTemplateInstance())
     {
@@ -664,14 +701,6 @@
         instance->TypeCheck(context);
         context.PopSetWeakArchetype();
     }
-    if (context.GetExtent() == TypeCheckExtent::body && !instance->IsArchetype())
-    {
-        CompilationUnitPtr compilationUnit = GetCompilationUnit();
-        ProjectPtr project = compilationUnit->GetProject();
-        CM_CORE_ASSERT(project);
-        TemplateRepositoryPtr templateRepository = project->GetTemplateRepository();
-        templateRepository->AddInstantiatedTemplate(instance);
-    }
     return instance;
 }
 
@@ -682,6 +711,9 @@
 
 bool Function::IsCopyConstructor() const
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(std::const_pointer_cast<Object>(shared_from_this()));
+#endif
     TypeCheckContext signature(TypeCheckExtent::signature);
     if (IsConstructor() && parameters.size() == 2)
     {
@@ -710,14 +742,14 @@
                                 NamePtr n = std::static_pointer_cast<Cm::Core::Name>(dte);
                                 n->TypeCheck(signature);
                                 dte = n->LinkedTo();
-                                CM_CORE_ASSERT(dte);
+                                CM_CORE_ASSERT(dte, fullName);
                             }
                             else if (dte->IsTemplateName())
                             {
                                 TemplateNamePtr n = std::static_pointer_cast<TemplateName>(dte);
                                 n->TypeCheck(signature);
                                 dte = n->GetType();
-                                CM_CORE_ASSERT(dte);
+                                CM_CORE_ASSERT(dte, fullName);
                             }
                             if (dte->IsType())
                             {
@@ -743,6 +775,9 @@
 
 bool Function::IsCopyAssignment() const
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(std::const_pointer_cast<Object>(shared_from_this()));
+#endif
     TypeCheckContext signature(TypeCheckExtent::signature);
     if (IsAssignment() && parameters.size() == 2)
     {
@@ -771,14 +806,14 @@
                                 NamePtr n = std::static_pointer_cast<Cm::Core::Name>(dte);
                                 n->TypeCheck(signature);
                                 dte = n->LinkedTo();
-                                CM_CORE_ASSERT(dte);
+                                CM_CORE_ASSERT(dte, fullName);
                             }
                             else if (dte->IsTemplateName())
                             {
                                 TemplateNamePtr n = std::static_pointer_cast<TemplateName>(dte);
                                 n->TypeCheck(signature);
                                 dte = n->GetType();
-                                CM_CORE_ASSERT(dte);
+                                CM_CORE_ASSERT(dte, fullName);
                             }
                             if (dte->IsType())
                             {
@@ -866,12 +901,15 @@
 bool Function::FindConversions(const ArgumentVector& arguments, ResolutionOption resolutionOption, ConversionOption conversion, 
     FunctionList& conversions, ConversionRank& conversionRank_, int& numConversions_, int& conversionDistance_, TypeCheckContext& context) 
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     conversionRank_ = conversionRank;
     numConversions_ = 0;
     conversionDistance_ = conversionDistance;
     SignatureChangeContext change(context);
     TypeCheck(context);
-    CM_CORE_ASSERT(parameters.size() == arguments.size());
+    CM_CORE_ASSERT(parameters.size() == arguments.size(), fullName);
     int n = parameters.size();
     for (int i = 0; i < n; ++i)
     {
@@ -905,7 +943,7 @@
         parameter->TypeCheck(context);
         TypePtr targetType = parameter->GetType();
         TypePtr originalTargetType = targetType;
-        CM_CORE_ASSERT(targetType);
+        CM_CORE_ASSERT(targetType, fullName);
         bool targetTypeIsConstRefType = false;
         bool targetTypeIsRefType = false;
         if (targetType->IsConstReferenceType())
@@ -1124,8 +1162,11 @@
 
 bool Function::CheckConstraint(const ExpressionList& templateArgs, ExceptionPtr& exception, const Position& callPosition, WhereConstraintPtr& whereConstraint)
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     ConstraintCheckContext ccctx;
-    CM_CORE_ASSERT(constraint);
+    CM_CORE_ASSERT(constraint, fullName);
     try
     {
         ScopePtr fileScope = FileScope();
@@ -1182,23 +1223,30 @@
     return false;
 }
 
-void Function::CollectExternalObjects(CompilationUnitPtr compilationUnit, ObjectSet& externalObjects, bool deep)
-{
-    if (GetInstantiationStatus() == InstantiationStatus::not_instantiated) return;
-    if (IsTemplate() || ExternalObjectsCollected(compilationUnit, deep)) return;
-    Object::CollectExternalObjects(compilationUnit, externalObjects, deep);
+void Function::CollectExternalObjects(CompilationUnitPtr compilationUnit)
+{
+    if (!CompilingForCodeGen()) return;
+    if (IsBasicTypeBuiltIn()) return;
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
+    CM_CORE_ASSERT(GetInstantiationStatus() != InstantiationStatus::not_instantiated, fullName);
+    if (externalCompilationUnits.find(compilationUnit) != externalCompilationUnits.end()) return;
+    externalCompilationUnits.insert(compilationUnit);
+    if (GetCompilationUnit() != compilationUnit || GetInstantiationStatus() == InstantiationStatus::present) 
+    {
+        compilationUnit->AddExternalObject(shared_from_this());
+        CM_CORE_ASSERT(GetCompilationUnit(), fullName);
+        GetCompilationUnit()->AddToDependents(compilationUnit);
+    }
     TypePtr returnType = GetReturnType();
     if (returnType)
     {
-        returnType->CollectExternalObjects(compilationUnit, externalObjects, false);
+        returnType->CollectExternalObjects(compilationUnit);
     }
     for (ParameterPtr parameter : parameters)
     {
-        parameter->CollectExternalObjects(compilationUnit, externalObjects, deep);
-    }
-    if (deep && body)
-    {
-        body->CollectExternalObjects(compilationUnit, externalObjects, deep);
+        parameter->CollectExternalObjects(compilationUnit);
     }
 }
 
@@ -1246,6 +1294,9 @@
 void Function::GenerateIntermediateCode(CodeFormatter& formatter)
 {
     if (IsExternal() || IsTemplate() || !body || IsArchetype()) return;
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     if (!stringObjects.empty())
     {
         for (ObjectPtr stringObject : stringObjects)
@@ -1261,7 +1312,7 @@
     body->CollectLocalVariables(localVariables);
     if (CanThrow() || IsDestructor())
     {
-        CM_CORE_ASSERT(exceptionCodeVariable);
+        CM_CORE_ASSERT(exceptionCodeVariable, fullName);
         exceptionCodeVariable->CollectLocalVariables(localVariables);
     }
     for (LocalVariablePtr localVariable : localVariables)
@@ -1273,7 +1324,7 @@
     body->GenReceiveCode(ir);
     if (CanThrow() || IsDestructor())
     {
-        CM_CORE_ASSERT(exceptionCodeVariable);
+        CM_CORE_ASSERT(exceptionCodeVariable, fullName);
         Llvm::Ir::Assign(ir, Llvm::Ir::I32(), Llvm::Ir::CreateI32Constant(0), exceptionCodeVariable->GetIrObject());
     }
     GenResult bodyResult = body->Gen(ir, GenFlags::label);
@@ -1312,7 +1363,7 @@
     }
 }
 
-void Function::GenerateExternalDeclaration(CodeFormatter& formatter)
+void Function::GenerateExternalDeclarations(CodeFormatter& formatter, CompilationUnitPtr forCompilationUnit)
 {
     irFun->WriteDeclaration(formatter);
 }
@@ -1322,7 +1373,9 @@
     if (instantiatedFromTemplate) return;
     if (IsDefault()) return;
     if (IsBasicTypeBuiltIn()) return;
-    if (functionSetName == "main") return;
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     std::string functionDeclaration = GetSpecifierStr(shared_from_this(), GetSpecifiers() | Specifiers::external);
     if (IsTemplate())
     {
@@ -1342,6 +1395,7 @@
         {
             constraintStr.append(" ").append(constraint->ToString());
         }
+        CM_CORE_ASSERT(GetCompilationUnit(), fullName);
         functionDeclaration.append(" function template ").append(instance->Name()).append(constraintStr).append(";[").append(IntToString(GetCompilationUnit()->Index())).append("]");
         formatter.WriteLine(functionDeclaration);
         AddNewObject(instance);
@@ -1457,57 +1511,6 @@
     return stringValue;
 }
 
-void Function::CheckIfCanThrow(bool& canThrow, TypeCheckContext& context)
-{
-    if (ArchetypeInstantiation() || ConstraintTypeChecking() || IsArchetype()) return;
-    if (IsVirtualAbstractOrOverride()) 
-    {
-        canThrow = true;
-        return;
-    }
-    if (checkedIfCanThrow)
-    {
-        if (CanThrow()) 
-        {
-            canThrow = true;
-        }
-        return;
-    }
-    bool debugNothrow = (GetFlags() & Flags::debugNothrow) != Flags::none; 
-    if (debugNothrow)
-    {
-        std::cout << "N> " << FullName() << std::endl; 
-    }
-    checkedIfCanThrow = true;
-    if (CanThrow())
-    {
-        if (body && !body->TypeChecking())
-        {
-            context.PushExtent(TypeCheckExtent::body);
-            body->TypeCheck(context);
-            body->CheckIfCanThrow(canThrow, context);
-            context.PopExtent();
-            if (!canThrow)
-            {
-                SetNothrow();
-                if (debugNothrow)
-                {
-                    std::cout << "N< " << FullName() << " set to nothrow" << std::endl; 
-                }
-                return;
-            }
-        }
-        else
-        {
-            canThrow = true;
-        }
-    }
-    if (debugNothrow)
-    {
-        std::cout << "N< " << FullName() << " keep non-nothrow" << std::endl; 
-    }
-}
-
 void Function::Print(CodeFormatter& formatter)
 {
     std::string s;
@@ -1529,9 +1532,12 @@
     instantiationStatus = instantiationStatus_;
 }
 
-void Function::MarkToBeInstantiated()
-{
-    instantiationStatus = InstantiationStatus::instantiated;
+void Function::Instantiate(TypeCheckContext& context)
+{
+    if (instantiationStatus == InstantiationStatus::not_instantiated)
+    {
+        instantiationStatus = InstantiationStatus::instantiated;
+    }
 }
 
 class FunctionTypeDirectory;
@@ -1594,7 +1600,7 @@
 
 FunctionTypeDirectoryPtr FunctionTypeDirectory::Instance()
 {
-    CM_CORE_ASSERT(instance);
+    CM_CORE_ASSERT(instance, nullptr);
     return instance;
 }
 
@@ -1648,6 +1654,7 @@
     static int initCount;
     DoNothingFunction(): Function("donothing", Position(), GlobalScope(), Cm::Core::ScopePtr(), "donothing", Specifiers::public_) 
     {
+        SetInstantiationStatus(InstantiationStatus::instantiated);
         SetIrFun(Llvm::Ir::CreateDoNothingFunction());
     }
 };
@@ -1674,7 +1681,7 @@
 
 DoNothingFunctionPtr DoNothingFunction::Instance()
 {
-    CM_CORE_ASSERT(instance);
+    CM_CORE_ASSERT(instance, nullptr);
     return instance;
 }
 
@@ -1686,9 +1693,12 @@
 FunctionCall::FunctionCall(FunctionPtr function_, const Position& pos_, Function* ownerFunction_, CompoundStatement* compound): 
     Object(function_->Name(), pos_, function_->EnclosingScope(), function_->FileScope()), function(function_), ownerFunction(ownerFunction_), landingPadCreated(false)
 {
-    if (!(ArchetypeInstantiation() || ConstraintTypeChecking() || EnumExprCheck() || ConstantExprCheck()))
-    {
-        CM_CORE_ASSERT(ownerFunction);
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(function);
+#endif
+    if (CompilingForCodeGen())
+    {
+        CM_CORE_ASSERT(ownerFunction, fullName);
     }
     SetCompound(compound);
 }
@@ -1746,7 +1756,7 @@
 {
     Object::TypeCheckSignature(context);
     function->TypeCheck(context);
-    if (!ArchetypeInstantiation() && !ConstraintTypeChecking() && !EnumExprCheck() && !ConstantExprCheck())
+    if (CompilingForCodeGen())
     {
         if (!ownerFunction->IsDestructor())
         {
@@ -1777,19 +1787,34 @@
 
 void FunctionCall::TypeCheckBody(TypeCheckContext& context)
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     Object::TypeCheckBody(context);
     context.PushExtent(TypeCheckExtent::signature);
     function->TypeCheck(context);
     context.PopExtent();
-    function->MarkToBeInstantiated();
+    if (CompilingForCodeGen())
+    {
+        function->Instantiate(context);
+        CM_CORE_ASSERT(ownerFunction, fullName);
+        CompilationUnitPtr thisCompilationUnit = ownerFunction->GetCompilationUnit();
+        if (thisCompilationUnit != function->GetCompilationUnit() || function->GetInstantiationStatus() == InstantiationStatus::present)
+        {
+            function->CollectExternalObjects(thisCompilationUnit);
+        }
+    }
 }
 
 void FunctionCall::GenerateDestructionStatements(DestructionStackPtr destructionStack)
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     Object::GenerateDestructionStatements(destructionStack);
     if (function->CanThrow() && !landingPadCreated)
     {
-        CM_CORE_ASSERT(ownerFunction->CanThrow() || ownerFunction->IsDestructor());
+        CM_CORE_ASSERT(ownerFunction->CanThrow() || ownerFunction->IsDestructor(), fullName);
         landingPadCreated = true;
         CompoundStatement* stopper = nullptr;
         TryStatementPtr tryStatement = destructionStack->GetTryStatement();
@@ -1813,6 +1838,9 @@
 
 void FunctionCall::Generate(Ir& ir, GenResult& result)
 {
+#if !defined(NDEBUG) || defined(ASSERTIONS)
+    const char* fullName = GetFullNameFor(shared_from_this());
+#endif
     if (function->CanThrow())
     {
         GenResult invokeResult(ir, result.Flags());
@@ -1825,7 +1853,7 @@
             invokeResult.SetMainObject(Llvm::Ir::ObjectPtr());
             invokeResult.AddObject(classObjectResultVar->GetIrObject());
         }
-        CM_CORE_ASSERT(ownerFunction->GetExceptionCodeVariable());
+        CM_CORE_ASSERT(ownerFunction->GetExceptionCodeVariable(), fullName);
         Llvm::Ir::ObjectPtr exceptionCodeVar = ownerFunction->GetExceptionCodeVariable()->GetIrObject();
         invokeResult.AddObject(exceptionCodeVar);
         function->Generate(ir, invokeResult);
@@ -1873,29 +1901,6 @@
     }
 }
 
-void FunctionCall::CollectExternalObjects(CompilationUnitPtr compilationUnit, ObjectSet& externalObjects, bool deep)
-{
-    if (ExternalObjectsCollected(compilationUnit, deep)) return;
-    Object::CollectExternalObjects(compilationUnit, externalObjects, deep);
-    if (!function->IsBasicTypeBuiltIn() && (function->GetCompilationUnit() != compilationUnit || function->GetInstantiationStatus() == InstantiationStatus::present))
-    {
-        externalObjects.insert(function);
-        if (function->GetCompilationUnit())
-        {
-            function->GetCompilationUnit()->AddToDependents(compilationUnit);
-        }
-        function->CollectExternalObjects(compilationUnit, externalObjects, false);
-    }
-}
-
-void FunctionCall::CheckIfCanThrow(bool& canThrow, TypeCheckContext& context)
-{
-    if (function->CanThrow())
-    {
-        function->CheckIfCanThrow(canThrow, context);
-    }
-}
-
 FunctionTemplateReference::FunctionTemplateReference(const std::string& name_, const Position& pos_, const ScopePtr& enclosingScope_, const ScopePtr& fileScope_, const std::string& functionSetName_, 
     Specifiers specifiers_): Function(name_, pos_, enclosingScope_, fileScope_, functionSetName_, specifiers_), sourceFileIndex(-1)
 {
@@ -1903,7 +1908,7 @@
 
 ObjectPtr FunctionTemplateReference::Clone(CloneContext& context) const
 {
-    CM_CORE_ASSERT(false);
+    CM_CORE_ASSERT(false, nullptr);
     return ObjectPtr();
 }