Преглед изворни кода

Squashed 'Source/ThirdParty/AngelScript/' changes from 886dc42a49..76c92e1a7e

76c92e1a7e Another attempt to merge upstream changes with local ones.
4407e00f81 Adapt to AngelScript 2.33.0 WIP.
2d1dcc5ace Travis CI: bump copyright to 2018. [cache clear]
632c3f505a Add macro for checking the compiler's C++11 type trait templates. Modify angelscript.h header file to use our custom compiler define based on the check result to cater for pre-standard Clang compiler toolchain.
a8c35e00c4 Remove "execute" permission in the source files. [ci skip]
faa58bc4f1 Allow possibility of building Urho3D without C++ exceptions feature. Disallow Android build to turn off C++ RTTI feature.
380964ffd8 Unconditionally disable the x86 syscall prologs / epilogs on GCC, since the assembler error related to cfi instructions could also happen on newer versions.
4944524d01 Old GCC version check in as_callfunc_x86.cpp for CI.
73aac66775 Restore Urho3D tweaks to as_config.h and earlier ifdef check for C++11 features.
d0dd6f54dc Restore earlier ifdef for AS type traits due to some Android CI builds failing.
53bf0c68b4 Clang internal error workaround to as_callfunc_x86.cpp
882e776ad1 Travis CI: bump copyright to 2017. [ccache clear]
b41f490557 Initial work to update to AngelScript 2.31.2.
4619fb1240 Move the bits into places.
3550aa1f60 - fixed a bug with symbol lookup introduced with the refactoring
2e3a756923 - fixed a bug with symbol lookup introduced with the refactoring
f86ebb43fc - Continued the refactoring of symbol lookup so both function calls and variable access use the same logic - Virtual property accessors must not have the same name as real property or function in the same scope
7265999643 - Refactored how he compiler does symbol lookups to better handle namespace hierarchies and child types. - The array's and string's length property accessor has been renamed to 'size' to avoid conflict with the length() method
270856ff08 The copy constructor of script classes are now used properly by the compiler
af2c56e2ad - Fixed problem with use of unsafe references and global variables
c9e4bb6040 - When unsafe references is allowed the stream operator (<<) can now be implemented on value types with correct behaviour for chained expressions - The asBC_REFCPY and asBC_RefCpyV instructions can now be used with value types too
0aa30f092b Fixed compiler error in as_callfunc_x86.cpp for gnuc/mingw when compiling with optimizations
7707e9a22c CScriptAny now supports forwarding gc enum callbacks to value types with gc behaviour
c598c98ad0 CScriptGrid now support forwarding gc enum callbacks to value types with gc behaviour
d0a44858e4 Included SetCircularRefDetectedCallback to allow application developers to easier identify the origin of circular references
2fea402a22 Fixed a bug when loading bytecode having identical shared functions in different namespaces
bf9480602b Fixed problem in compiler that didn't release a temporary variable when passing anonymous object to function expecting ?&in
0a32333cf9 - AssignScriptObject will now set a script exception for ref types if asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE is used - Initialization lists will implicitly assume objects by handle if asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE is used
1ef192e4cc Passing a string literal to function expecting &out will now give compiler error
5c154f1ccb Fixed bug introduced in previous revision
71d557fd6d Fixed assert failure on call to opCast(?&out) with a non-variable expression
fbfc3cbc5c Bytecode with external shared classes with virtual methods failed to load from bytecode
5b97a695c8 The bytecode for external shared entities is no longer saved in the module when inherited from (additional fix when the same function was used in another class too)
3b7448cd61 The bytecode for external shared entities is no longer saved in the module when inherited from
21e4c65fb7 Fixed loading byte code that uses external shared classes in namespace
19cb3e303f Reduced the size of the saved byte code, especially when there are lots of functions without parameters
ce6fe5b80b CScriptDictionary now supports forwarding gc enum callbacks to value types with gc behaviour
c102cf24a3 Added exception handling to the MSVC8 project
3af7bab9d5 Initializing an ASHANDLE type with overloaded opHndlAssign taking a var type as a handle wasn't done correctly
11600f0d96 - Added the engine methods ForwardGCEnumReferences and ForwardGCReleaseAllReferences - CScriptArray now supports forwarding gc enum callbacks to value types with gc behaviour
d787280628 - Registered value types can now register GC behaviours to solve circular references involving these types - CScriptHandle registers the ENUMREFS and RELEASEREFS gc behaviours
db6a199d60 CScriptBuilder now supports having multiple meta data blocks for each entity
e6da96550a auto declarations now works correctly with implicit handle types
45194c3cf6 Fixed bug when loading bytecode containing shared interfaces with inheritance
6c6f887d26 meta data is now correctly extracted for class methods with decorators
f982e0dc2a The correct resolution is now done for types implementing both opCast and opImplConv and the const overloads. The same for opConv and opImplConv
7716d5479f Added MSVC 2017 projects
e7368f62a8 Fixed compiler error when both opConv and opImplConv are implemented
6fafba3022 opImplCast with variable type won't be used for non-ref types
f8a9eaed89 Fixed memory build-up due to delayed cleanup when discarding modules with shared entities
1649f60370 Further fixes related to template types and namespaces
14b56414db Template types are now properly identified in separate namespaces
f0ed5e519f Fixed an error when compiling a class method call as post-op and the name matches a type name
e3ca22c65a Saving bytecode for a never returning function would cause assert failure
c8095307f3 Class constructors can now be declared with private and protected too
64ab05ba0c Fixed error when saving bytecode for scripts containing interfaces that derives from interfaces
8bd5d40097 weakref now properly identifies different object instance when the address is the same as the previously freed object
cbaa500fb3 Fixed compiler error on Linux
d0e37c201b Implemented a callback to allow application to translate C++ exceptions thrown by registered functions
8037ae9a51 By default asEP_GENERIC_CALL_MODE is set to use the new behaviour
ef7d9a44ad Implemented engine property asEP_GENERIC_CALL_MODE to make the generic calling convention treat handles the same way that the native calling convention do
f15dcfcc56 Compiler would crash on compiling ternary operator with anonymous list in one of the conditions
aa7d45b60e Template types can now be registered with methods taking parameters as &inout
12c7ab4d6c - Loading bytecode that included use of template value types with a template type as argument crashed - All methods for template instances now get unique functions to show the template instance as the object type
32c4b235ba documentation
18678f1da9 The compiler will now give an error on bitwise operator with floats instead of silently converting to integer
400c54c299 Fixed bug with anonymous initialization lists when used to initialize value type passed by value to function
c168f89b4b - Fixed crash in debugger add-on when printing call stack in template function - Documented the script grammar in BNF - Added support for specifying parameter types to lambda functions
80adf56b06 Minor refactoring to reduce some duplicated code for verifying if proceeding token sequence is a type
d8e324cad1 Engine error messages now include the symbol name for the error code for easier interpretation
c6803b2a0a - Implemented a #pragma callback in the builder add-on - asrun can now turn on debugging with #pragma debug (works the same as -d command arg)
42c35611d6 Fixed incorrect use of setlocale in parseFloat
18fc360ef2 Changed the compiler to do less copies of objects and especially string constants
ba12d89ea0 cmake changes
9c93ca0c69 Fixed crash when compiling is null comparison with ASHANDLE object without any opEquals operator
66e4471016 Changed the clean-up of the string factory in the stdstring add-on to avoid crash if the script engine is stored in global singleton
1eb058cf24 - filesystem's changeCurrentPath doesn't modify anything if the new path is invalid - Implemented the methods makeDir, removeDir, deleteFile, copyFile, and move on the filesystem add-on
76aeadd7f3 Updated the cmake project for better usability
bfd447ddcb The asrun sample now waits for user input before closing on any error when executed from file explorer on Windows
153b385a1f Preparing the tests for new optimizations
4dd0bd304a Added methods setDate and setTime to datetime add-on and operators to add seconds, compare, and determine difference in seconds
d50e15345c Added the methods IsLink and GetSize to filesystem add-on
315252e5d1 Releasing 2.32.0
117d6a49cd Updating the config according to the new way of registering the string factory
833178fcaf RefCastObject was allowing explicit cast from base class to derived class even though the true type was of the base class
d582d62bf4 Linux with ARM doesn't support catching c++ exceptions yet
4232d7c0c8 Fixed problem on platforms where char is unsigned by default
c13e697abd Removed unnecessary include
0270b00838 Increased initial buffer size in asCString::Format to work around problem on Linux
3f5163be6c Fixed compiler warning
827c153abe Fixed buffer overflow when formatting error message with very long tokens
028f4cf94e Testing long tokens
8b279427dd Corrections for Linux/GNUC
5257e9234e Fixed an incorrect default arg
38fb52292f - Implemented generic calling convention for the CScriptArray::Sort method with callback - Fixed compiler error with AS_NO_COMPILER - Fixed tests for AS_MAX_PORTABILITY
8a5f493719 Documentation
680bde46d5 - Documentation - Removed the option to turn off the new string factory
11f1654449 Documentation
a49a9b59ba Documentation
12d2dcae4d Documentation
cdc47e3c1f Documentation
00b102d455 - Object properties can also be registered for composite objects - WriteConfigToStream and ConfigEngineFromStream properly handles composite properties - Debugger is capable of inspecting value of composite properties
d0896a561c Added support for registering class methods for composite types
737a4dc5c0 Removed deprecated code from previous versions
c503c760b9 Changed how string literals are handled by the script engine. Now they are evaluated at compile time and a pointer to the application native string object is stored in the byte code.
6f3df65557 Cleaning up
fc9738dc20 Compiler was allowing to pass a const object by reference to a parameter expecting a non-const when using unsafe references
18cc16c9fd Saved byte code with scripts that used child funcdefs couldn't be loaded
699cd4806f Value type without opAssign but with a copy constructor can now be implicitly copied in type conversions
af1cd92622 Explicitly creating a copy of a const object to get a non-const handle would give a compiler error
6672b26d13 - Objects that rely on asGetActiveContext during clean-up can now do so even during exception handling - Dictionary storing a const handle now allows retrieving by value
c5ad0228ab cleaning up the test code a bit
03d1e39c1e more cleanup in test code
8b44cde9b4 - Both Read and Write in asIBinaryStream can now return an error code to signal failure - fixed compiler warnings in test applications
49f44eaffa Fixed compilation error when the project path included space characters
026b87b5b6 Code clean-up
99d5a7d155 Using bit fields for function traits
4f6b4f38f0 Fixed the asbuild sample config and script files
aa74157748 Minor code cleanup
923f709dd3 Fixed assert failure when compiling expression with anonymous initialization list
f61dc2abc3 Fixed assert failure while compiling unary minus operator on constant integers smaller than 32 bits.
570966664a Fixed crash in compiler when compiling type conversion with invalid use of named arguments
393403156b Fixed assert failure when compiling comparison expressions with primitives smaller than 32bit
f610f7ed14 Fixed compiler error in deprecated IsHandleCompatibleWithObject when using AS_DEPRECATED
3d0c058e3c Handles received by reference is now properly treated when passed to function expecting variant type
cb4ddab368 Improved compiler error message when identifier before parenthesis doesn't evaluate to a function
REVERT: 886dc42a49 Allow possibility of building Urho3D without C++ exceptions feature. Disallow Android build to turn off C++ RTTI feature.
REVERT: 465d6931ea Unconditionally disable the x86 syscall prologs / epilogs on GCC, since the assembler error related to cfi instructions could also happen on newer versions.
REVERT: cb0ee7d3a4 Old GCC version check in as_callfunc_x86.cpp for CI.
REVERT: 63489c0d82 Restore Urho3D tweaks to as_config.h and earlier ifdef check for C++11 features.
REVERT: 4d24a82c7f Restore earlier ifdef for AS type traits due to some Android CI builds failing.
REVERT: 29bb3e80ec Clang internal error workaround to as_callfunc_x86.cpp
REVERT: 456770f542 Travis CI: bump copyright to 2017. [ccache clear]
REVERT: 522ff404ba Initial work to update to AngelScript 2.31.2.
REVERT: 05e50a5c70 Move the bits into places.

git-subtree-dir: Source/ThirdParty/AngelScript
git-subtree-split: 76c92e1a7e333abfb8827d0c5dc1c9a651e527f3
Yao Wei Tjong 姚伟忠 пре 7 година
родитељ
комит
13d333a335

+ 4 - 1
CMakeLists.txt

@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2008-2017 the Urho3D project.
+# Copyright (c) 2008-2018 the Urho3D project.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,9 @@
 set (TARGET_NAME AngelScript)
 
 # Define preprocessor macros
+if (CLANG_PRE_STANDARD)
+    add_definitions (-DCLANG_PRE_STANDARD)
+endif ()
 if (NOT EXCEPTIONS)
     add_definitions (-DAS_NO_EXCEPTIONS)
 endif ()

+ 43 - 80
include/angelscript.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -28,7 +28,7 @@
    [email protected]
 */
 
-// Modified by Lasse Oorni and Nathanial Lydick for Urho3D
+// Modified by Lasse Oorni, Nathanial Lydick, and Yao Wei Tjong for Urho3D
 
 //
 // angelscript.h
@@ -64,8 +64,8 @@ BEGIN_AS_NAMESPACE
 
 // AngelScript version
 
-#define ANGELSCRIPT_VERSION        23200
-#define ANGELSCRIPT_VERSION_STRING "2.32.0 WIP"
+#define ANGELSCRIPT_VERSION        23300
+#define ANGELSCRIPT_VERSION_STRING "2.33.0 WIP"
 
 // Data types
 
@@ -75,15 +75,12 @@ class asIScriptContext;
 class asIScriptGeneric;
 class asIScriptObject;
 class asITypeInfo;
-#ifdef AS_DEPRECATED
-// deprecated since 2.31.0 - 2015/11/18
-typedef asITypeInfo asIObjectType;
-#endif
 class asIScriptFunction;
 class asIBinaryStream;
 class asIJITCompiler;
 class asIThreadManager;
 class asILockableSharedBool;
+class asIStringFactory;
 
 // Enumerations and constants
 
@@ -151,6 +148,7 @@ enum asEEngineProp
 	asEP_ALLOW_UNICODE_IDENTIFIERS          = 25,
 	asEP_HEREDOC_TRIM_MODE                  = 26,
 	asEP_MAX_NESTED_CALLS                   = 27,
+	asEP_GENERIC_CALL_MODE                  = 28,
 
 	asEP_LAST_PROPERTY
 };
@@ -238,14 +236,6 @@ enum asEBehaviours
 	asBEHAVE_GET_WEAKREF_FLAG,
 
 	// Object operators
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.30.0, 2014-10-24
-	asBEHAVE_VALUE_CAST,
-	asBEHAVE_IMPLICIT_VALUE_CAST,
-	// Deprecated since 2.30.0, 2014-12-30
-	asBEHAVE_REF_CAST,
-	asBEHAVE_IMPLICIT_REF_CAST,
-#endif
 	asBEHAVE_TEMPLATE_CALLBACK,
 
 	// Garbage collection behaviours
@@ -369,6 +359,8 @@ enum asEFuncType
 // asQWORD = 64 bits
 // asPWORD = size of pointer
 //
+typedef signed char    asINT8;
+typedef signed short   asINT16;
 typedef unsigned char  asBYTE;
 typedef unsigned short asWORD;
 typedef unsigned int   asUINT;
@@ -411,24 +403,20 @@ typedef void (*asCLEANMODULEFUNC_t)(asIScriptModule *);
 typedef void (*asCLEANCONTEXTFUNC_t)(asIScriptContext *);
 typedef void (*asCLEANFUNCTIONFUNC_t)(asIScriptFunction *);
 typedef void (*asCLEANTYPEINFOFUNC_t)(asITypeInfo *);
-#ifdef AS_DEPRECATED
-// deprecated since 2.31.0 - 2015/11/18
-typedef asCLEANTYPEINFOFUNC_t asCLEANOBJECTTYPEFUNC_t;
-#endif
 typedef void (*asCLEANSCRIPTOBJECTFUNC_t)(asIScriptObject *);
 typedef asIScriptContext *(*asREQUESTCONTEXTFUNC_t)(asIScriptEngine *, void *);
 typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, void *);
+typedef void (*asCIRCULARREFFUNC_t)(asITypeInfo *, const void *, void *);
 
 // Check if the compiler can use C++11 features
-// Urho3D: restored earlier ifdef
 #if !defined(_MSC_VER) || _MSC_VER >= 1700   // MSVC 2012
-#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)  // gnuc 4.7
-#if !(defined(__GNUC__) && defined(__cplusplus) && __cplusplus < 201103L) // g++ -std=c++11
-#if !defined(__SUNPRO_CC)
-#define AS_CAN_USE_CPP11 1
-#endif
-#endif
-#endif
+ #if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)  // gnuc 4.7 or clang
+  #if !(defined(__GNUC__) && defined(__cplusplus) && __cplusplus < 201103L) // gnuc and clang require compiler flag -std=c++11
+   #if !defined(__SUNPRO_CC) // Oracle Solaris Studio
+    #define AS_CAN_USE_CPP11 1
+   #endif
+  #endif
+ #endif
 #endif
 
 // This macro does basically the same thing as offsetof defined in stddef.h, but
@@ -442,9 +430,6 @@ typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, voi
 // check that the cast is really valid.
 // BCC v5.8 (C++Builder 2006) and earlier have a similar bug which forces us to fall back to a C-style cast.
 #define asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())((r (*)p)(f)))
-#elif (defined(_MSC_VER) && _MSC_VER >= 1900)
-// Urho3D: VS2015 does not compile the C-style cast of the function pointer
-#define asFUNCTIONPR(f,p,r) asFunctionPtr(reinterpret_cast<void (*)()>(static_cast<r (*)p>(f)))
 #else
 #define asFUNCTIONPR(f,p,r) asFunctionPtr(reinterpret_cast<void (*)()>(static_cast<r (*)p>(f)))
 #endif
@@ -605,15 +590,15 @@ BEGIN_AS_NAMESPACE
 template<typename T>
 asUINT asGetTypeTraits()
 {
-// Urho3D: restore earlier ifdefs due to some Android CI builds breaking
-#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5)
+// Urho3D - Clang compiler built with old GCC's libstdc++ suffers the same pre-standard templates problem as old GCC compiler
+#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5) || (defined(__clang__) && !defined(CLANG_PRE_STANDARD))
 	// MSVC, XCode/Clang, and gnuc 5+
 	// C++11 compliant code
 	bool hasConstructor        = std::is_default_constructible<T>::value && !std::is_trivially_default_constructible<T>::value;
 	bool hasDestructor         = std::is_destructible<T>::value          && !std::is_trivially_destructible<T>::value;
 	bool hasAssignmentOperator = std::is_copy_assignable<T>::value       && !std::is_trivially_copy_assignable<T>::value;
 	bool hasCopyConstructor    = std::is_copy_constructible<T>::value    && !std::is_trivially_copy_constructible<T>::value;
-#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__)
 	// gnuc 4.8 is using a mix of C++11 standard and pre-standard templates
 	bool hasConstructor        = std::is_default_constructible<T>::value && !std::has_trivial_default_constructor<T>::value;
 	bool hasDestructor         = std::is_destructible<T>::value          && !std::is_trivially_destructible<T>::value;
@@ -701,21 +686,16 @@ public:
 
 	// Object types
 	virtual int            RegisterObjectType(const char *obj, int byteSize, asDWORD flags) = 0;
-	virtual int            RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset) = 0;
-	virtual int            RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0) = 0;
-	virtual int            RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0) = 0;
+	virtual int            RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset = 0, bool isCompositeIndirect = false) = 0;
+	virtual int            RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false) = 0;
+	virtual int            RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false) = 0;
 	virtual int            RegisterInterface(const char *name) = 0;
 	virtual int            RegisterInterfaceMethod(const char *intf, const char *declaration) = 0;
 	virtual asUINT         GetObjectTypeCount() const = 0;
 	virtual asITypeInfo   *GetObjectTypeByIndex(asUINT index) const = 0;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual asITypeInfo   *GetObjectTypeByName(const char *name) const = 0;
-	virtual asITypeInfo   *GetObjectTypeByDecl(const char *decl) const = 0;
-#endif
 
 	// String factory
-	virtual int RegisterStringFactory(const char *datatype, const asSFuncPtr &factoryFunc, asDWORD callConv, void *auxiliary = 0) = 0;
+	virtual int RegisterStringFactory(const char *datatype, asIStringFactory *factory) = 0;
 	virtual int GetStringFactoryReturnTypeId(asDWORD *flags = 0) const = 0;
 
 	// Default array type
@@ -727,10 +707,6 @@ public:
 	virtual int          RegisterEnumValue(const char *type, const char *name, int value) = 0;
 	virtual asUINT       GetEnumCount() const = 0;
 	virtual asITypeInfo *GetEnumByIndex(asUINT index) const = 0;
-	// Urho3D: Removed deprecation for ScriptAPIDump
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual int          GetEnumValueCount(int enumTypeId) const = 0;
-	virtual const char * GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const = 0;
 
 	// Funcdefs
 	virtual int          RegisterFuncdef(const char *decl) = 0;
@@ -758,16 +734,8 @@ public:
 
 	// Script functions
 	virtual asIScriptFunction *GetFunctionById(int funcId) const = 0;
-#ifdef AS_DEPRECATED
-	// deprecated since 2.31.0, 2016-01-01
-	virtual asIScriptFunction *GetFuncdefFromTypeId(int typeId) const = 0;
-#endif
 
 	// Type identification
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual asITypeInfo   *GetObjectTypeById(int typeId) const = 0;
-#endif
 	virtual int            GetTypeIdByDecl(const char *decl) const = 0;
 	virtual const char    *GetTypeDeclaration(int typeId, bool includeNamespace = false) const = 0;
 	virtual int            GetSizeOfPrimitiveType(int typeId) const = 0;
@@ -785,10 +753,6 @@ public:
 	virtual void                   ReleaseScriptObject(void *obj, const asITypeInfo *type) = 0;
 	virtual void                   AddRefScriptObject(void *obj, const asITypeInfo *type) = 0;
 	virtual int                    RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo *toType, void **newPtr, bool useOnlyImplicitCast = false) = 0;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.30.0, 2014-11-04
-	virtual bool                   IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const = 0;
-#endif
 	virtual asILockableSharedBool *GetWeakRefFlagOfScriptObject(void *obj, const asITypeInfo *type) const = 0;
 
 	// Context pooling
@@ -805,6 +769,9 @@ public:
 	virtual int  NotifyGarbageCollectorOfNewObject(void *obj, asITypeInfo *type) = 0;
 	virtual int  GetObjectInGC(asUINT idx, asUINT *seqNbr = 0, void **obj = 0, asITypeInfo **type = 0) = 0;
 	virtual void GCEnumCallback(void *reference) = 0;
+	virtual void ForwardGCEnumReferences(void *ref, asITypeInfo *type) = 0;
+	virtual void ForwardGCReleaseReferences(void *ref, asITypeInfo *type) = 0;
+	virtual void SetCircularRefDetectedCallback(asCIRCULARREFFUNC_t callback, void *param = 0) = 0;
 
 	// User data
 	virtual void *SetUserData(void *data, asPWORD type = 0) = 0;
@@ -813,17 +780,27 @@ public:
 	virtual void  SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback, asPWORD type = 0) = 0;
 	virtual void  SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback, asPWORD type = 0) = 0;
 	virtual void  SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback, asPWORD type = 0) = 0;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual void  SetObjectTypeUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type = 0) = 0;
-#endif
 	virtual void  SetTypeInfoUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type = 0) = 0;
 	virtual void  SetScriptObjectUserDataCleanupCallback(asCLEANSCRIPTOBJECTFUNC_t callback, asPWORD type = 0) = 0;
 
+	// Exception handling
+	virtual int SetTranslateAppExceptionCallback(asSFuncPtr callback, void *param, int callConv) = 0;
+
 protected:
 	virtual ~asIScriptEngine() {}
 };
 
+class asIStringFactory
+{
+public:
+	virtual const void *GetStringConstant(const char *data, asUINT length) = 0;
+	virtual int         ReleaseStringConstant(const void *str) = 0;
+	virtual int         GetRawStringData(const void *str, char *data, asUINT *length) const = 0;
+
+protected:
+	virtual ~asIStringFactory() {}
+};
+
 class asIThreadManager
 {
 protected:
@@ -867,11 +844,6 @@ public:
 	// Type identification
 	virtual asUINT         GetObjectTypeCount() const = 0;
 	virtual asITypeInfo   *GetObjectTypeByIndex(asUINT index) const = 0;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual asITypeInfo   *GetObjectTypeByName(const char *name) const = 0;
-	virtual asITypeInfo   *GetObjectTypeByDecl(const char *decl) const = 0;
-#endif
 	virtual int            GetTypeIdByDecl(const char *decl) const = 0;
 	virtual asITypeInfo   *GetTypeInfoByName(const char *name) const = 0;
 	virtual asITypeInfo   *GetTypeInfoByDecl(const char *decl) const = 0;
@@ -879,11 +851,6 @@ public:
 	// Enums
 	virtual asUINT       GetEnumCount() const = 0;
 	virtual asITypeInfo *GetEnumByIndex(asUINT index) const = 0;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual int          GetEnumValueCount(int enumTypeId) const = 0;
-	virtual const char * GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const = 0;
-#endif
 
 	// Typedefs
 	virtual asUINT       GetTypedefCount() const = 0;
@@ -1104,7 +1071,7 @@ public:
 
 	// Properties
 	virtual asUINT      GetPropertyCount() const = 0;
-	virtual int         GetProperty(asUINT index, const char **name, int *typeId = 0, bool *isPrivate = 0, bool *isProtected = 0, int *offset = 0, bool *isReference = 0, asDWORD *accessMask = 0) const = 0;
+	virtual int         GetProperty(asUINT index, const char **name, int *typeId = 0, bool *isPrivate = 0, bool *isProtected = 0, int *offset = 0, bool *isReference = 0, asDWORD *accessMask = 0, int *compositeOffset = 0, bool *isCompositeIndirect = 0) const = 0;
 	virtual const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const = 0;
 
 	// Behaviours
@@ -1167,10 +1134,6 @@ public:
 	virtual bool             IsShared() const = 0;
 	virtual asUINT           GetParamCount() const = 0;
 	virtual int              GetParam(asUINT index, int *typeId, asDWORD *flags = 0, const char **name = 0, const char **defaultArg = 0) const = 0;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.29.0, 2014-04-06
-	virtual int              GetParamTypeId(asUINT index, asDWORD *flags = 0) const = 0;
-#endif
 	virtual int              GetReturnTypeId(asDWORD *flags = 0) const = 0;
 
 	// Type id for function pointers
@@ -1202,8 +1165,8 @@ protected:
 class asIBinaryStream
 {
 public:
-	virtual void Read(void *ptr, asUINT size) = 0;
-	virtual void Write(const void *ptr, asUINT size) = 0;
+	virtual int Read(void *ptr, asUINT size) = 0;
+	virtual int Write(const void *ptr, asUINT size) = 0;
 
 public:
 	virtual ~asIBinaryStream() {}

+ 1 - 1
include/wrap.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2017 the Urho3D project.
+// Copyright (c) 2008-2018 the Urho3D project.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal

+ 1 - 3
include/wrap16.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2017 the Urho3D project.
+// Copyright (c) 2008-2018 the Urho3D project.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -147,8 +147,6 @@
 #define RegisterObjectBehaviorFPRasCALL_GENERIC(clsdcl,behavior,decl,...) RegisterObjectBehaviour(clsdcl,behavior,decl, _asFUNCTIONPR(__VA_ARGS__), asCALL_GENERIC);
 #define RegisterObjectBehaviorFPRasCALL_CDECL(clsdcl,behavior,decl,clsfunc) RegisterObjectBehaviour(clsdcl,behavior,decl, WRAP_FN_PR clsfunc, asCALL_GENERIC);
 
-#define RegisterStringFactory(...) EV(RegisterStringFactory_2(__VA_ARGS__))
-#define RegisterStringFactory_2(str,F,params,kind) RegisterStringFactory(str, WRAP_FN (params), asCALL_GENERIC);
 
 /*#define SetExceptionCallback(...) SetExceptionCallback_2(__VA_ARGS__)
 #define SetExceptionCallback_2(M,params,obj,kind) SetExceptionCallback(WRAP_MFN params, obj, asCALL_GENERIC);

+ 175 - 188
source/as_builder.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -280,11 +280,11 @@ int asCBuilder::Build()
 	Reset();
 
 	// The template callbacks must only be called after the subtypes have a known structure,
-	// otherwise the callback may think it is not possible to create the template instance, 
+	// otherwise the callback may think it is not possible to create the template instance,
 	// even though it is.
-	// TODO: This flag shouldn't be set globally in the engine, as it would mean that another 
-	//       thread requesting a template instance in parallel to the compilation wouldn't 
-	//       evaluate the template instance. 
+	// TODO: This flag shouldn't be set globally in the engine, as it would mean that another
+	//       thread requesting a template instance in parallel to the compilation wouldn't
+	//       evaluate the template instance.
 	engine->deferValidationOfTemplateTypes = true;
 	asUINT numTempl = (asUINT)engine->templateInstanceTypes.GetLength();
 
@@ -294,7 +294,7 @@ int asCBuilder::Build()
 	CompileInterfaces();
 	CompileClasses(numTempl);
 
-	// Evaluate the template instances one last time, this time with error messages, as we know 
+	// Evaluate the template instances one last time, this time with error messages, as we know
 	// all classes have been fully built and it is known which ones will need garbage collection.
 	EvaluateTemplateInstances(numTempl, false);
 	engine->deferValidationOfTemplateTypes = false;
@@ -377,7 +377,7 @@ int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int
 	if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
 		WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
 
-	// None of the functions should be added to the module if any error occurred, 
+	// None of the functions should be added to the module if any error occurred,
 	// or it was requested that the functions wouldn't be added to the scope
 	if( numErrors > 0 )
 	{
@@ -521,12 +521,12 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 	node = node->firstChild;
 
 	// Create the function
-	bool isConstructor, isDestructor, isPrivate, isProtected, isFinal, isOverride, isShared, isExternal;
+	asSFunctionTraits funcTraits;
 	asCScriptFunction *func = asNEW(asCScriptFunction)(engine, compileFlags & asCOMP_ADD_TO_MODULE ? module : 0, asFUNC_SCRIPT);
 	if( func == 0 )
 		return asOUT_OF_MEMORY;
 
-	GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isProtected, isFinal, isOverride, isShared, isExternal, module->defaultNamespace);
+	GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, funcTraits, module->defaultNamespace);
 	func->id                           = engine->GetNextScriptFunctionId();
 	func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
 	int row, col;
@@ -553,7 +553,7 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 		}
 
 		module->globalFunctions.Put(func);
-		
+
 		module->AddScriptFunction(func);
 	}
 	else
@@ -589,7 +589,7 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 	if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
 		WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
 
-	// None of the functions should be added to the module if any error occurred, 
+	// None of the functions should be added to the module if any error occurred,
 	// or it was requested that the functions wouldn't be added to the scope
 	if( !(compileFlags & asCOMP_ADD_TO_MODULE) || numErrors > 0 )
 	{
@@ -1141,7 +1141,7 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace
 			if( isPureConstant ) *isPureConstant = globDesc->isPureConstant;
 			if( constantValue  ) *constantValue  = globDesc->constantValue;
 		}
-		else 
+		else
 #endif
 		if( isAppProp )
 		{
@@ -1269,7 +1269,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 
 		// Move to next parameter
 		n = n->next->next;
-		if( n && n->nodeType == snIdentifier ) 
+		if( n && n->nodeType == snIdentifier )
 		{
 			func->parameterNames[index] = asCString(&source.code[n->tokenPos], n->tokenLength);
 			n = n->next;
@@ -1298,17 +1298,17 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 	{
 		if( objType == 0 )
 			return asINVALID_DECLARATION;
-		func->isReadOnly = true;
+		func->SetReadOnly(true);
 
 		n = n->next;
 	}
 	else
-		func->isReadOnly = false;
+		func->SetReadOnly(false);
 
 	// If the caller expects a list pattern, check for the existence, else report an error if not
 	if( listPattern )
 	{
-		if( n == 0 || n->nodeType != snListPattern ) 
+		if( n == 0 || n->nodeType != snListPattern )
 			return asINVALID_DECLARATION;
 		else
 		{
@@ -1321,7 +1321,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 		if( n )
 			return asINVALID_DECLARATION;
 	}
-	
+
 	// Make sure the default args are declared correctly
 	ValidateDefaultArgs(&source, node, func);
 
@@ -1605,22 +1605,14 @@ int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNam
 void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 {
 	asCArray<asCString *>      defaultArgs;
-	bool                       isConstMethod;
-	bool                       isConstructor;
-	bool                       isDestructor;
-	bool                       isProtected;
-	bool                       isPrivate;
-	bool                       isOverride;
-	bool                       isFinal;
-	bool                       isShared;
-	bool                       isExternal;
+	asSFunctionTraits          funcTraits;
 
 	asCFuncdefType *fdt = module->funcDefs[funcDef->idx];
 	asASSERT( fdt );
 	asCScriptFunction *func = fdt->funcdef;
 
 	asSNameSpace *implicitNs = func->nameSpace ? func->nameSpace : fdt->parentClass->nameSpace;
-	GetParsedFunctionDetails(funcDef->node, funcDef->script, fdt->parentClass, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, isExternal, implicitNs);
+	GetParsedFunctionDetails(funcDef->node, funcDef->script, fdt->parentClass, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, funcTraits, implicitNs);
 
 	// There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks
 	for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
@@ -1628,8 +1620,8 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 			asDELETE(defaultArgs[n], asCString);
 
 	// All funcdefs are shared, unless one of the parameter types or return type is not shared
-	bool declaredShared = isShared;
-	isShared = true;
+	bool declaredShared = funcTraits.GetTrait(asTRAIT_SHARED);
+	funcTraits.SetTrait(asTRAIT_SHARED, true);
 	if (func->returnType.GetTypeInfo() && !func->returnType.GetTypeInfo()->IsShared())
 	{
 		if (declaredShared)
@@ -1638,9 +1630,9 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 			s.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, func->returnType.GetTypeInfo()->name.AddressOf());
 			WriteError(s.AddressOf(), funcDef->script, funcDef->node);
 		}
-		isShared = false;
+		funcTraits.SetTrait(asTRAIT_SHARED, false);
 	}
-	for( asUINT n = 0; isShared && n < func->parameterTypes.GetLength(); n++ )
+	for( asUINT n = 0; funcTraits.GetTrait(asTRAIT_SHARED) && n < func->parameterTypes.GetLength(); n++ )
 		if (func->parameterTypes[n].GetTypeInfo() && !func->parameterTypes[n].GetTypeInfo()->IsShared())
 		{
 			if (declaredShared)
@@ -1649,13 +1641,13 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 				s.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, func->parameterTypes[n].GetTypeInfo()->name.AddressOf());
 				WriteError(s.AddressOf(), funcDef->script, funcDef->node);
 			}
-			isShared = false;
+			funcTraits.SetTrait(asTRAIT_SHARED, false);
 		}
-	func->isShared = isShared;
+	func->SetShared(funcTraits.GetTrait(asTRAIT_SHARED));
 
 	// Check if there is another identical funcdef from another module and if so reuse that instead
 	bool found = false;
-	if( func->isShared )
+	if( func->IsShared() )
 	{
 		for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
 		{
@@ -1663,7 +1655,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 			if( fdt2 == 0 || fdt == fdt2 )
 				continue;
 
-			if( !fdt2->funcdef->isShared )
+			if( !fdt2->funcdef->IsShared() )
 				continue;
 
 			if( fdt2->name == fdt->name &&
@@ -1685,7 +1677,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 	}
 
 	// If the funcdef was declared as external then the existing shared declaration must have been found
-	if (isExternal && !found)
+	if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !found)
 	{
 		asCString str;
 		str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, funcDef->name.AddressOf());
@@ -1693,7 +1685,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 	}
 
 	// Remember if the type was declared as external so the saved bytecode can be flagged accordingly
-	if (isExternal && found)
+	if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && found)
 		module->externalTypes.PushLast(engine->scriptFunctions[funcDef->idx]->funcdefType);
 }
 
@@ -2696,7 +2688,7 @@ void asCBuilder::DetermineTypeRelations()
 		node = node->firstChild;
 
 		// Skip the 'shared' & 'external' keywords
-		while( node->nodeType == snIdentifier && 
+		while( node->nodeType == snIdentifier &&
 			   (intfDecl->script->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) ||
 				intfDecl->script->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN)) )
 			node = node->next;
@@ -3303,7 +3295,7 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 				asCDataType dt = prop->type;
 
 				// TODO: Add this check again, once solving the issues commented below
-				/* 
+				/*
 				if( dt.IsTemplate() )
 				{
 					// TODO: This must verify all sub types, not just the first one
@@ -3409,7 +3401,7 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 	{
 		if( numReevaluations > typesToValidate.GetLength() )
 		{
-			// No types could be completely evaluated in the last iteration so 
+			// No types could be completely evaluated in the last iteration so
 			// we consider the remaining types in the array as garbage collected
 			break;
 		}
@@ -3434,7 +3426,7 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 
 		// Evaluate template instances (silently) before verifying each of the classes, since it is possible that
 		// a class will be marked as non-garbage collected, which in turn will mark the template instance that uses
-		// it as non-garbage collected, which in turn means the class that contains the array also do not have to be 
+		// it as non-garbage collected, which in turn means the class that contains the array also do not have to be
 		// garbage collected
 		EvaluateTemplateInstances(numTempl, true);
 
@@ -3448,7 +3440,7 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 
 			if (dt.IsFuncdef())
 			{
-				// If a class holds a function pointer as member then the class must be garbage collected as the 
+				// If a class holds a function pointer as member then the class must be garbage collected as the
 				// function pointer can form circular references with the class through use of a delegate. Example:
 				//
 				//   class A { B @b; void f(); }
@@ -3540,7 +3532,7 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 					else if( prop->flags & asOBJ_GC )
 					{
 						// If a type is not a script object, adopt its GC flag
-						// TODO: runtime optimize: Just because an application registered class is garbage collected, doesn't mean it 
+						// TODO: runtime optimize: Just because an application registered class is garbage collected, doesn't mean it
 						//                         can form a circular reference with this script class. Perhaps need a flag to tell
 						//                         if the script classes that contains the type should be garbage collected or not.
 						gc = true;
@@ -3557,8 +3549,8 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 			}
 		}
 
-		// If the class wasn't found to require garbage collection, but it 
-		// contains another type that has yet to be evaluated then it must be 
+		// If the class wasn't found to require garbage collection, but it
+		// contains another type that has yet to be evaluated then it must be
 		// re-evaluated.
 		if( !gc && mustReevaluate )
 		{
@@ -3605,11 +3597,11 @@ void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl)
 		sMixinClass *mixin = 0;
 		while( ns )
 		{
-			// Need to make sure the name is not an object type 
+			// Need to make sure the name is not an object type
 			asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
 			if( objType == 0 )
 				mixin = GetMixinClass(name.AddressOf(), ns);
-			
+
 			if( objType || mixin )
 				break;
 
@@ -3679,11 +3671,11 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl)
 		sMixinClass *mixin = 0;
 		while( ns )
 		{
-			// Need to make sure the name is not an object type 
+			// Need to make sure the name is not an object type
 			asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
 			if( objType == 0 )
 				mixin = GetMixinClass(name.AddressOf(), ns);
-			
+
 			if( objType || mixin )
 				break;
 
@@ -3807,19 +3799,19 @@ int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
 		return asOUT_OF_MEMORY;
 
 	vf->name             = func->name;
+	vf->nameSpace        = func->nameSpace;
 	vf->returnType       = func->returnType;
 	vf->parameterTypes   = func->parameterTypes;
 	vf->inOutFlags       = func->inOutFlags;
 	vf->id               = engine->GetNextScriptFunctionId();
-	vf->isReadOnly       = func->isReadOnly;
 	vf->objectType       = func->objectType;
 	vf->objectType->AddRefInternal();
 	vf->signatureId      = func->signatureId;
-	vf->isPrivate        = func->isPrivate;
-	vf->isProtected      = func->isProtected;
-	vf->isFinal          = func->isFinal;
-	vf->isOverride       = func->isOverride;
 	vf->vfTableIdx       = idx;
+	vf->traits           = func->traits;
+
+	// Clear the shared trait since the virtual function should not have that
+	vf->SetShared(false);
 
 	// It is not necessary to copy the default args, as they have no meaning in the virtual function
 
@@ -3888,7 +3880,7 @@ bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *m
 
 		if( m->name           != method->name           ) continue;
 		if( m->returnType     != method->returnType     ) continue;
-		if( m->isReadOnly     != method->isReadOnly     ) continue;
+		if( m->IsReadOnly()   != method->IsReadOnly()   ) continue;
 		if( m->parameterTypes != method->parameterTypes ) continue;
 		if( m->inOutFlags     != method->inOutFlags     ) continue;
 
@@ -3913,7 +3905,7 @@ void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *fi
 
 	// Add the script function
 	// TODO: declaredAt should be set to where the class has been declared
-	module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType, false, false, false, false, false, false, false, objType->nameSpace);
+	module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType, false, asSFunctionTraits(), objType->nameSpace);
 
 	// Set it as default constructor
 	if( objType->beh.construct )
@@ -3956,7 +3948,7 @@ void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *fi
 
 	// If the object is shared, then the factory must also be marked as shared
 	if( objType->flags & asOBJ_SHARED )
-		engine->scriptFunctions[funcId]->isShared = true;
+		engine->scriptFunctions[funcId]->SetShared(true);
 }
 
 int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
@@ -4141,7 +4133,7 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp
 				gvar->ns                 = ns;
 				// No need to allocate space on the global memory stack since the values are stored in the asCObjectType
 				// Set the index to a negative to allow compiler to diferentiate from ordinary global var when compiling the initialization
-				gvar->index              = -1; 
+				gvar->index              = -1;
 				gvar->isCompiled         = false;
 				gvar->isPureConstant     = true;
 				gvar->isEnumValue        = true;
@@ -4224,40 +4216,41 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam
 	return r;
 }
 
-void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isProtected, bool &isOverride, bool &isFinal, bool &isShared, bool &isExternal, asSNameSpace *implicitNamespace)
+void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, asSFunctionTraits &funcTraits, asSNameSpace *implicitNamespace)
 {
 	node = node->firstChild;
 
 	// Is the function shared?
-	isShared = false;
-	isExternal = false;
+	funcTraits.SetTrait(asTRAIT_SHARED, false);
+	funcTraits.SetTrait(asTRAIT_EXTERNAL, false);
 	while (node->tokenType == ttIdentifier)
 	{
 		if (file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN))
-			isShared = true;
+			funcTraits.SetTrait(asTRAIT_SHARED, true);
 		else if (file->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN))
-			isExternal = true;
+			funcTraits.SetTrait(asTRAIT_EXTERNAL, true);
 		else
 			break;
 		node = node->next;
 	}
 
 	// Is the function a private or protected class method?
-	isPrivate = false, isProtected = false;
+	funcTraits.SetTrait(asTRAIT_PRIVATE, false);
+	funcTraits.SetTrait(asTRAIT_PROTECTED, false);
 	if( node->tokenType == ttPrivate )
 	{
-		isPrivate = true;
+		funcTraits.SetTrait(asTRAIT_PRIVATE, true);
 		node = node->next;
 	}
 	else if( node->tokenType == ttProtected )
 	{
-		isProtected = true;
+		funcTraits.SetTrait(asTRAIT_PROTECTED, true);
 		node = node->next;
 	}
 
 	// Find the name
-	isConstructor = false;
-	isDestructor = false;
+	funcTraits.SetTrait(asTRAIT_CONSTRUCTOR, false);
+	funcTraits.SetTrait(asTRAIT_DESTRUCTOR, false);
 	asCScriptNode *n = 0;
 	if( node->nodeType == snDataType )
 		n = node->next->next;
@@ -4267,17 +4260,17 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi
 		if( node->tokenType == ttBitNot )
 		{
 			n = node->next;
-			isDestructor = true;
+			funcTraits.SetTrait(asTRAIT_DESTRUCTOR, true);
 		}
 		else
 		{
 			n = node;
-			isConstructor = true;
+			funcTraits.SetTrait(asTRAIT_CONSTRUCTOR, true);
 		}
 	}
 	name.Assign(&file->code[n->tokenPos], n->tokenLength);
 
-	if( !isConstructor && !isDestructor )
+	if( !funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) && !funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
 	{
 		returnType = CreateDataTypeFromNode(node, file, implicitNamespace, false, objType);
 		returnType = ModifyDataTypeFromNode(returnType, node->next, file, 0, 0);
@@ -4286,7 +4279,7 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi
 			returnType.GetTypeInfo() &&
 			(returnType.GetTypeInfo()->flags & asOBJ_REF) &&
 			!(returnType.GetTypeInfo()->flags & asOBJ_SCOPED) &&
-			!returnType.IsReference() && 
+			!returnType.IsReference() &&
 			!returnType.IsObjectHandle() )
 		{
 			WriteError(TXT_REF_TYPE_CANT_BE_RETURNED_BY_VAL, file, node);
@@ -4295,9 +4288,9 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi
 	else
 		returnType = asCDataType::CreatePrimitive(ttVoid, false);
 
-	isConstMethod = false;
-	isFinal = false;
-	isOverride = false;
+	funcTraits.SetTrait(asTRAIT_CONST, false);
+	funcTraits.SetTrait(asTRAIT_FINAL, false);
+	funcTraits.SetTrait(asTRAIT_OVERRIDE, false);
 
 	if( objType && n->next->next )
 	{
@@ -4306,16 +4299,16 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi
 		// Is this a const method?
 		if( decorator->tokenType == ttConst )
 		{
-			isConstMethod = true;
+			funcTraits.SetTrait(asTRAIT_CONST, true);
 			decorator = decorator->next;
 		}
 
 		while( decorator )
 		{
 			if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN) )
-				isFinal = true;
+				funcTraits.SetTrait(asTRAIT_FINAL, true);
 			else if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN) )
-				isOverride = true;
+				funcTraits.SetTrait(asTRAIT_OVERRIDE, true);
 
 			decorator = decorator->next;
 		}
@@ -4350,7 +4343,7 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi
 			type.GetTypeInfo() &&
 			(type.GetTypeInfo()->flags & asOBJ_REF) &&
 			!(type.GetTypeInfo()->flags & asOBJ_SCOPED) &&
-			!type.IsReference() && 
+			!type.IsReference() &&
 			!type.IsObjectHandle() )
 		{
 			WriteError(TXT_REF_TYPE_CANT_BE_PASSED_BY_VAL, file, node);
@@ -4422,15 +4415,7 @@ int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCod
 	asCArray<asCDataType>      parameterTypes;
 	asCArray<asETypeModifiers> inOutFlags;
 	asCArray<asCString *>      defaultArgs;
-	bool                       isConstMethod;
-	bool                       isOverride;
-	bool                       isFinal;
-	bool                       isConstructor;
-	bool                       isDestructor;
-	bool                       isPrivate;
-	bool                       isProtected;
-	bool                       isShared;
-	bool                       isExternal;
+	asSFunctionTraits          funcTraits;
 
 	asASSERT( (objType && ns == 0) || isGlobalFunction || isMixin );
 
@@ -4443,9 +4428,9 @@ int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCod
 			ns = engine->nameSpaces[0];
 	}
 
-	GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, isExternal, ns);
+	GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns);
 
-	return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, isExternal);
+	return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits);
 }
 
 asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns)
@@ -4454,12 +4439,15 @@ asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode
 	asCArray<asCString> parameterNames;
 	asCArray<asCString*> defaultArgs;
 	asCScriptNode *args = node->firstChild;
-	while( args && args->nodeType == snIdentifier )
+	while( args && args->nodeType != snStatementBlock )
 	{
-		asCString argName;
-		argName.Assign(&file->code[args->tokenPos], args->tokenLength);
-		parameterNames.PushLast(argName);
-		defaultArgs.PushLast(0);
+		if (args->nodeType == snIdentifier)
+		{
+			asCString argName;
+			argName.Assign(&file->code[args->tokenPos], args->tokenLength);
+			parameterNames.PushLast(argName);
+			defaultArgs.PushLast(0);
+		}
 		args = args->next;
 	}
 
@@ -4468,7 +4456,7 @@ asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode
 
 	// Get the return and parameter types from the funcDef
 	asCString funcName = name;
-	int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, false, false, false, false, false, false, false, false, false);
+	int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, asSFunctionTraits());
 	if( r < 0 )
 		return 0;
 
@@ -4476,7 +4464,7 @@ asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode
 	return engine->scriptFunctions[functions[functions.GetLength()-1]->funcId];
 }
 
-int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared, bool isExternal)
+int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, asSFunctionTraits funcTraits)
 {
 	// Determine default namespace if not specified
 	if( ns == 0 )
@@ -4493,7 +4481,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 
 		// Should validate that the function really exists in the class/interface
 		bool found = false;
-		if( isConstructor || isDestructor )
+		if(funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) || funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
 		{
 			// TODO: shared: Should check the existance of these too
 			found = true;
@@ -4504,7 +4492,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 			{
 				asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
 				if( func->name == name &&
-					func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) )
+					func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
 				{
 					// Add the shared function in this module too
 					module->AddScriptFunction(func);
@@ -4532,7 +4520,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 	}
 
 	// Check for name conflicts
-	if( !isConstructor && !isDestructor )
+	if( !funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) && !funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
 	{
 		if( objType )
 		{
@@ -4564,14 +4552,14 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		if( name != objType->name )
 		{
 			asCString str;
-			if( isDestructor )
+			if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
 				str.Format(TXT_DESTRUCTOR_s_s_NAME_ERROR, objType->name.AddressOf(), name.AddressOf());
 			else
 				str.Format(TXT_METHOD_s_s_HAS_NO_RETURN_TYPE, objType->name.AddressOf(), name.AddressOf());
 			WriteError(str, file, node);
 		}
 
-		if( isDestructor )
+		if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR))
 			name = "~" + name;
 	}
 
@@ -4600,14 +4588,14 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		func->isExistingShared  = false;
 		func->paramNames        = parameterNames;
 
-		if( isShared )
+		if(funcTraits.GetTrait(asTRAIT_SHARED))
 		{
 			// Look for a pre-existing shared function with the same signature
 			for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
 			{
 				asCScriptFunction *f = engine->scriptFunctions[n];
 				if( f &&
-					f->isShared &&
+					f->IsShared() &&
 					f->name == name &&
 					f->nameSpace == ns &&
 					f->objectType == objType &&
@@ -4621,10 +4609,10 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		}
 
 		// Remember if the function was declared as external so the saved bytecode can be flagged accordingly
-		if (isExternal && func->isExistingShared)
+		if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && func->isExistingShared)
 			module->externalFunctions.PushLast(engine->scriptFunctions[func->funcId]);
 
-		if (isExternal && !func->isExistingShared)
+		if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !func->isExistingShared)
 		{
 			// Mark it as existing shared to avoid compiling it
 			func->isExistingShared = true;
@@ -4635,13 +4623,13 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		}
 
 		// External shared function must not try to redefine the interface
-		if (isExternal && !(node->tokenType == ttEndStatement || node->lastChild->tokenType == ttEndStatement))
+		if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !(node->tokenType == ttEndStatement || node->lastChild->tokenType == ttEndStatement))
 		{
 			asCString str;
 			str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf());
 			WriteError(str, file, node);
 		}
-		else if (!isExternal && !(node->nodeType == snStatementBlock || node->lastChild->nodeType == snStatementBlock) )
+		else if (!funcTraits.GetTrait(asTRAIT_EXTERNAL) && !(node->nodeType == snStatementBlock || node->lastChild->nodeType == snStatementBlock) )
 		{
 			asCString str;
 			str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf());
@@ -4650,11 +4638,11 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 	}
 
 	// Destructors may not have any parameters
-	if (isDestructor && parameterTypes.GetLength() > 0)
+	if (funcTraits.GetTrait(asTRAIT_DESTRUCTOR) && parameterTypes.GetLength() > 0)
 		WriteError(TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, file, node);
 
 	// If a function, class, or interface is shared then only shared types may be used in the signature
-	if( (objType && objType->IsShared()) || isShared )
+	if( (objType && objType->IsShared()) || funcTraits.GetTrait(asTRAIT_SHARED))
 	{
 		asCTypeInfo *ti = returnType.GetTypeInfo();
 		if( ti && !ti->IsShared() )
@@ -4688,7 +4676,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		for( asUINT n = 0; n < funcs.GetLength(); ++n )
 		{
 			asCScriptFunction *func = GetFunctionDescription(funcs[n]);
-			if( func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) )
+			if( func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
 			{
 				// TODO: clean up: Reuse the same error handling for both opConv and normal methods
 				if( isMixin )
@@ -4717,7 +4705,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		for( asUINT n = 0; n < funcs.GetLength(); ++n )
 		{
 			asCScriptFunction *func = GetFunctionDescription(funcs[n]);
-			if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, isConstMethod) )
+			if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
 			{
 				if( isMixin )
 				{
@@ -4760,7 +4748,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		int row = 0, col = 0;
 		if( node )
 			file->ConvertPosToRowCol(node->tokenPos, &row, &col);
-		module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isConstMethod, isGlobalFunction, isPrivate, isProtected, isFinal, isOverride, isShared, ns);
+		module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isGlobalFunction, funcTraits, ns);
 	}
 
 	// Make sure the default args are declared correctly
@@ -4772,7 +4760,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		asASSERT( !isExistingShared );
 
 		engine->scriptFunctions[funcId]->AddRefInternal();
-		if( isConstructor )
+		if(funcTraits.GetTrait(asTRAIT_CONSTRUCTOR))
 		{
 			int factoryId = engine->GetNextScriptFunctionId();
 			if( parameterTypes.GetLength() == 0 )
@@ -4789,6 +4777,19 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 			}
 			else
 			{
+				// The copy constructor needs to be marked for easy finding
+				if (parameterTypes.GetLength() == 1 && parameterTypes[0].GetTypeInfo() == objType)
+				{
+					// Verify that there are not multiple options matching the copy constructor
+					// TODO: Need a better message, since the parameters can be slightly different, e.g. & vs @
+					if( objType->beh.copyconstruct )
+						WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
+
+					objType->beh.copyconstruct = funcId;
+					objType->beh.copyfactory = factoryId;
+				}
+
+				// Register as a normal constructor
 				objType->beh.constructors.PushLast(funcId);
 
 				// Register the factory as well
@@ -4801,11 +4802,11 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 					defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
 
 			asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
-			module->AddScriptFunction(file->idx, engine->scriptFunctions[funcId]->scriptData->declaredAt, factoryId, name, dt, parameterTypes, parameterNames, inOutFlags, defaultArgs, false);
+			module->AddScriptFunction(file->idx, engine->scriptFunctions[funcId]->scriptData->declaredAt, factoryId, name, dt, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, 0, false, funcTraits);
 
 			// If the object is shared, then the factory must also be marked as shared
 			if( objType->flags & asOBJ_SHARED )
-				engine->scriptFunctions[factoryId]->isShared = true;
+				engine->scriptFunctions[factoryId]->SetShared(true);
 
 			// Add a dummy function to the builder so that it doesn't mix up the fund Ids
 			functions.PushLast(0);
@@ -4815,7 +4816,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 			compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
 			engine->scriptFunctions[factoryId]->AddRefInternal();
 		}
-		else if( isDestructor )
+		else if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR))
 			objType->beh.destruct = funcId;
 		else
 		{
@@ -4887,14 +4888,12 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file
 		WriteError(TXT_PROPERTY_WITHOUT_ACCESSOR, file, node);
 
 	node = node->next;
-	while( node )
+	while (node)
 	{
-		asCScriptNode             *next        = node->next;
-		asCScriptNode             *funcNode    = 0;
-		bool                       success     = false;
-		bool                       isConst     = false;
-		bool                       isFinal     = false;
-		bool                       isOverride  = false;
+		asCScriptNode             *next = node->next;
+		asCScriptNode             *funcNode = 0;
+		bool                       success = false;
+		asSFunctionTraits          funcTraits;
 		asCDataType                returnType;
 		asCArray<asCString>        paramNames;
 		asCArray<asCDataType>      paramTypes;
@@ -4902,33 +4901,44 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file
 		asCArray<asCString*>       defaultArgs;
 		asCString                  name;
 
+		funcTraits.SetTrait(asTRAIT_PRIVATE, isPrivate);
+		funcTraits.SetTrait(asTRAIT_PROTECTED, isProtected);
+
 		// TODO: getset: Allow private for individual property accessors
 		// TODO: getset: If the accessor uses its own name, then the property should be automatically declared
 
-		if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN) )
+		if (node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN))
+			name = "get_";
+		else if (node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN))
+			name = "set_";
+		else
+			WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node);
+
+		if (name != "")
 		{
-			funcNode  = node->firstChild->next;
+			success = true;
+			funcNode = node->firstChild->next;
 
-			if( funcNode && funcNode->tokenType == ttConst )
+			if (funcNode && funcNode->tokenType == ttConst)
 			{
-				isConst = true;
+				funcTraits.SetTrait(asTRAIT_CONST, true);
 				funcNode = funcNode->next;
 			}
 
-			while( funcNode && funcNode->nodeType != snStatementBlock )
+			while (funcNode && funcNode->nodeType != snStatementBlock)
 			{
-				if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
-					isFinal = true;
-				else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
-					isOverride = true;
+				if (funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN))
+					funcTraits.SetTrait(asTRAIT_FINAL, true);
+				else if (funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN))
+					funcTraits.SetTrait(asTRAIT_OVERRIDE, true);
 
 				funcNode = funcNode->next;
 			}
 
-			if( funcNode )
+			if (funcNode)
 				funcNode->DisconnectParent();
 
-			if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
+			if (funcNode == 0 && (objType == 0 || !objType->IsInterface()))
 			{
 				// TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation
 				//               The compiler needs to be able to handle the different types, primitive, value type, and handle
@@ -4936,53 +4946,28 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file
 				WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
 			}
 
-			// Setup the signature for the get accessor method
-			returnType = emulatedType;
-			name       = "get_" + emulatedName;
-			success    = true;
-		}
-		else if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN) )
-		{
-			funcNode  = node->firstChild->next;
-
-			if( funcNode && funcNode->tokenType == ttConst )
+			if (name == "get_")
 			{
-				isConst = true;
-				funcNode = funcNode->next;
+				// Setup the signature for the get accessor method
+				returnType = emulatedType;
+				name = "get_" + emulatedName;
 			}
-
-			while( funcNode && funcNode->nodeType != snStatementBlock )
+			else if (name == "set_")
 			{
-				if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
-					isFinal = true;
-				else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
-					isOverride = true;
-
-				funcNode = funcNode->next;
+				// Setup the signature for the set accessor method
+				returnType = asCDataType::CreatePrimitive(ttVoid, false);
+				paramModifiers.PushLast(asTM_NONE);
+				paramNames.PushLast("value");
+				paramTypes.PushLast(emulatedType);
+				defaultArgs.PushLast(0);
+				name = "set_" + emulatedName;
 			}
-
-			if( funcNode )
-				funcNode->DisconnectParent();
-
-			if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
-				WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
-
-			// Setup the signature for the set accessor method
-			returnType = asCDataType::CreatePrimitive(ttVoid, false);
-			paramModifiers.PushLast(asTM_NONE);
-			paramNames.PushLast("value");
-			paramTypes.PushLast(emulatedType);
-			defaultArgs.PushLast(0);
-			name = "set_" + emulatedName;
-			success = true;
 		}
-		else
-			WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node);
 
 		if( success )
 		{
 			if( !isExistingShared )
-				RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, isConst, false, false, isPrivate, isProtected, isOverride, isFinal, false, false);
+				RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, funcTraits);
 			else
 			{
 				// Free the funcNode as it won't be used
@@ -4994,7 +4979,7 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file
 				{
 					asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
 					if( func->name == name &&
-						func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, isConst) )
+						func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
 					{
 						found = true;
 						break;
@@ -5026,12 +5011,12 @@ int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCS
 	asCArray<asCDataType>      parameterTypes;
 	asCArray<asETypeModifiers> inOutFlags;
 	asCArray<asCString *>      defaultArgs;
-	bool isConstMethod, isOverride, isFinal, isConstructor, isDestructor, isPrivate, isProtected, isShared, isExternal;
+	asSFunctionTraits          funcTraits;
 
 	if( ns == 0 )
 		ns = engine->nameSpaces[0];
 
-	GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, isExternal, ns);
+	GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns);
 	CheckNameConflict(name.AddressOf(), node, file, ns);
 
 	// Check that the same function hasn't been registered already in the namespace
@@ -5118,7 +5103,7 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob
 		asASSERT( errNode && script );
 
 		// If the scope contains ::identifier, then use the last identifier as the class name and the rest of it as the namespace
-		// TODO: child funcdef: A scope can include a template type, e.g. array<ns::type> 
+		// TODO: child funcdef: A scope can include a template type, e.g. array<ns::type>
 		int n = scope.FindLast("::");
 		asCString className = n >= 0 ? scope.SubString(n+2) : scope;
 		asCString nsName = n >= 0 ? scope.SubString(0, n) : "";
@@ -5131,8 +5116,8 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob
 				ns = engine->nameSpaces[0];
 			else
 				ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script, 0, false);
-			
-			// If the namespace isn't found return silently and let the calling 
+
+			// If the namespace isn't found return silently and let the calling
 			// function report the error if it cannot resolve the symbol
 			if (ns == 0)
 				return;
@@ -5160,7 +5145,7 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob
 	{
 		asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]];
 		if( func->name == name &&
-			(!objIsConst || func->isReadOnly) &&
+			(!objIsConst || func->IsReadOnly()) &&
 			(func->accessMask & module->accessMask) )
 		{
 			// When the scope is defined the returned methods should be the true methods, not the virtual method stubs
@@ -5416,7 +5401,7 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod
 	if (isValid)
 		*isValid = true;
 
-	// If the informed node is an identifier or scope, then the 
+	// If the informed node is an identifier or scope, then the
 	// datatype should be identified directly from that
 	if (node->nodeType != snDataType)
 		n = node;
@@ -5686,7 +5671,7 @@ asCObjectType *asCBuilder::GetTemplateInstanceFromNode(asCScriptNode *node, asCS
 	{
 		n = n->next;
 
-		// When parsing function definitions for template registrations (currentType != 0) it is necessary 
+		// When parsing function definitions for template registrations (currentType != 0) it is necessary
 		// to pass in the current template type to the recursive call since it is this ones sub-template types
 		// that should be allowed.
 		asCDataType subType = CreateDataTypeFromNode(n, file, implicitNamespace, false, module ? 0 : (currentType ? currentType : templateType));
@@ -5805,10 +5790,12 @@ asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScrip
 		}
 
 		if( !engine->ep.allowUnsafeReferences &&
-			inOutFlags && *inOutFlags == asTM_INOUTREF )
+			inOutFlags && *inOutFlags == asTM_INOUTREF &&
+			!(dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE)) )
 		{
 			// Verify that the base type support &inout parameter types
-			if( !dt.IsObject() || dt.IsObjectHandle() || !((dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || (CastToObjectType(dt.GetTypeInfo())->beh.addref && CastToObjectType(dt.GetTypeInfo())->beh.release)) )
+			if( !dt.IsObject() || dt.IsObjectHandle() || 
+				!((dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || (CastToObjectType(dt.GetTypeInfo())->beh.addref && CastToObjectType(dt.GetTypeInfo())->beh.release)) )
 				WriteError(TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, file, node->firstChild);
 		}
 	}
@@ -5818,7 +5805,7 @@ asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScrip
 	if( n && n->tokenType == ttPlus )
 	{
 		// Autohandles are not supported for types with NOCOUNT
-		// If the type is not a handle then there was an error with building the type, but 
+		// If the type is not a handle then there was an error with building the type, but
 		// this error would already have been reported so no need to report another error here
 		if( dt.IsObjectHandle() && (dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) )
 			WriteError(TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT, file, node->firstChild);
@@ -5912,17 +5899,17 @@ bool asCBuilder::DoesTypeExist(const asCString &type)
 			for (n = 0; n < module->classTypes.GetLength(); n++)
 				if (!knownTypes.MoveTo(0, module->classTypes[n]->name))
 					knownTypes.Insert(module->classTypes[n]->name, true);
-		
+
 			// Add script enums
 			for (n = 0; n < module->enumTypes.GetLength(); n++)
 				if (!knownTypes.MoveTo(0, module->enumTypes[n]->name))
 					knownTypes.Insert(module->enumTypes[n]->name, true);
-		
+
 			// Add script typedefs
 			for (n = 0; n < module->typeDefs.GetLength(); n++)
 				if (!knownTypes.MoveTo(0, module->typeDefs[n]->name))
 					knownTypes.Insert(module->typeDefs[n]->name, true);
-		
+
 			// Add script funcdefs
 			for (n = 0; n < module->funcDefs.GetLength(); n++)
 				if (!knownTypes.MoveTo(0, module->funcDefs[n]->name))

+ 10 - 10
source/as_builder.h

@@ -2,23 +2,23 @@
    AngelCode Scripting Library
    Copyright (c) 2003-2017 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -206,7 +206,7 @@ protected:
 	void               AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin);
 
 	int                RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false, bool isMixin = false);
-	int                RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared, bool isExternal);
+	int                RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, asSFunctionTraits funcTraits);
 	int                RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false);
 	int                RegisterImportedFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
 	int                RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
@@ -220,7 +220,7 @@ protected:
 	void               CompileInterfaces();
 	void               CompileClasses(asUINT originalNumTempl);
 	void               DetermineTypeRelations();
-	void               GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isProtected, bool &isOverride, bool &isFinal, bool &isShared, bool &isExternal, asSNameSpace *implicitNamespace);
+	void               GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, asSFunctionTraits &traits, asSNameSpace *implicitNamespace);
 	bool               DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex = 0);
 	void               AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file);
 	asCObjectProperty *AddPropertyToClass(sClassDeclaration *c, const asCString &name, const asCDataType &type, bool isPrivate, bool isProtected, bool isInherited, asCScriptCode *file = 0, asCScriptNode *node = 0);

+ 30 - 11
source/as_bytecode.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -2116,7 +2116,7 @@ void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func)
 	{
 		int idx = func->scriptData->objVariablePos.IndexOf(func->scriptData->variables[n]->stackOffset);
 		bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
-		fprintf(file, " %.3d: %s%s %s\n", func->scriptData->variables[n]->stackOffset, isOnHeap ? "(heap) " : "", func->scriptData->variables[n]->type.Format(func->nameSpace).AddressOf(), func->scriptData->variables[n]->name.AddressOf());
+		fprintf(file, " %.3d: %s%s %s\n", func->scriptData->variables[n]->stackOffset, isOnHeap ? "(heap) " : "", func->scriptData->variables[n]->type.Format(func->nameSpace, true).AddressOf(), func->scriptData->variables[n]->name.AddressOf());
 	}
 	asUINT offset = 0;
 	if( func->objectType )
@@ -2139,7 +2139,7 @@ void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func)
 		{
 			int idx = func->scriptData->objVariablePos.IndexOf(offset);
 			bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
-			fprintf(file, " %.3d: %s%s {noname param}\n", offset, isOnHeap ? "(heap) " : "", func->parameterTypes[n].Format(func->nameSpace).AddressOf());
+			fprintf(file, " %.3d: %s%s {noname param}\n", offset, isOnHeap ? "(heap) " : "", func->parameterTypes[n].Format(func->nameSpace, true).AddressOf());
 		}
 
 		offset -= func->parameterTypes[n].GetSizeOnStackDWords();
@@ -2199,14 +2199,7 @@ void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func)
 		switch( asBCInfo[instr->op].type )
 		{
 		case asBCTYPE_W_ARG:
-			if( instr->op == asBC_STR )
-			{
-				int id = asWORD(instr->wArg[0]);
-				const asCString &str = engine->GetConstantString(id);
-				fprintf(file, "   %-8s %d         (l:%ld s:\"%.10s\")\n", asBCInfo[instr->op].name, asWORD(instr->wArg[0]), (long int)str.GetLength(), str.AddressOf());
-			}
-			else
-				fprintf(file, "   %-8s %d\n", asBCInfo[instr->op].name, instr->wArg[0]);
+			fprintf(file, "   %-8s %d\n", asBCInfo[instr->op].name, instr->wArg[0]);
 			break;
 
 		case asBCTYPE_wW_ARG:
@@ -2315,6 +2308,32 @@ void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func)
 					fprintf(file, "   %-8s 0x%x          (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), f->GetDeclaration());
 				}
 				break;
+
+			case asBC_PGA:
+				{
+					void *ptr = *(void**)ARG_QW(instr->arg);
+					asSMapNode<void*, asCGlobalProperty*> *cursor = 0;
+					if( engine->varAddressMap.MoveTo(&cursor, ptr) )
+					{
+						fprintf(file, "   %-8s 0x%x          (var:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), cursor->value->name.AddressOf());
+					}
+					else
+					{
+						asUINT length;
+						engine->stringFactory->GetRawStringData(ptr, 0, &length);
+						asCString str;
+						str.SetLength(length);
+						engine->stringFactory->GetRawStringData(ptr, str.AddressOf(), &length);
+						if (str.GetLength() > 20)
+						{
+							// TODO: Replace non-visible characters with space or something like it
+							str.SetLength(20);
+							str += "...";
+						}
+						fprintf(file, "   %-8s 0x%x          (str:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), str.AddressOf());
+					}
+				}
+				break;
 	
 			default:
 #ifdef __GNUC__

+ 56 - 38
source/as_callfunc.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -99,7 +99,7 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv,
 		else
 			return asNOT_SUPPORTED;
 	}
-	
+
 	if( isMethod )
 	{
 #ifndef AS_NO_CLASS_METHODS
@@ -187,25 +187,37 @@ int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInter
 		{
 			if (dt.IsFuncdef())
 			{
-				asSSystemFunctionInterface::SClean clean;
-				clean.op = 0; // call release
-				clean.ot = &engine->functionBehaviours;
-				clean.off = short(offset);
-				internal->cleanArgs.PushLast(clean);
-			}
-			else if( dt.GetTypeInfo()->flags & asOBJ_REF )
-			{
-				asSTypeBehaviour *beh = &CastToObjectType(dt.GetTypeInfo())->beh;
-				asASSERT( (dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || beh->release );
-				if( beh->release )
+				// If the generic call mode is set to old behaviour then always release handles
+				// else only release the handle if the function is declared with auto handles
+				if (engine->ep.genericCallMode == 0 || (internal->paramAutoHandles.GetLength() > n && internal->paramAutoHandles[n]))
 				{
 					asSSystemFunctionInterface::SClean clean;
-					clean.op  = 0; // call release
-					clean.ot  = CastToObjectType(dt.GetTypeInfo());
+					clean.op = 0; // call release
+					clean.ot = &engine->functionBehaviours;
 					clean.off = short(offset);
 					internal->cleanArgs.PushLast(clean);
 				}
 			}
+			else if( dt.GetTypeInfo()->flags & asOBJ_REF )
+			{
+				// If the generic call mode is set to old behaviour then always release handles
+				// else only release the handle if the function is declared with auto handles
+				if (!dt.IsObjectHandle() ||
+					engine->ep.genericCallMode == 0 || 
+					(internal->paramAutoHandles.GetLength() > n && internal->paramAutoHandles[n]) )
+				{
+					asSTypeBehaviour *beh = &CastToObjectType(dt.GetTypeInfo())->beh;
+					asASSERT((dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || beh->release);
+					if (beh->release)
+					{
+						asSSystemFunctionInterface::SClean clean;
+						clean.op = 0; // call release
+						clean.ot = CastToObjectType(dt.GetTypeInfo());
+						clean.off = short(offset);
+						internal->cleanArgs.PushLast(clean);
+					}
+				}
+			}
 			else
 			{
 				asSSystemFunctionInterface::SClean clean;
@@ -239,7 +251,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
 	UNUSED_VAR(internal);
 	UNUSED_VAR(engine);
 
-	// This should never happen, as when AS_MAX_PORTABILITY is on, all functions 
+	// This should never happen, as when AS_MAX_PORTABILITY is on, all functions
 	// are asCALL_GENERIC, which are prepared by PrepareSystemFunctionGeneric
 	asASSERT(false);
 #else
@@ -254,7 +266,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
 	else if( func->returnType.IsObject() )
 	{
 		asDWORD objType = func->returnType.GetTypeInfo()->flags;
-	
+
 		// Only value types can be returned by value
 		asASSERT( objType & asOBJ_VALUE );
 
@@ -425,7 +437,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
 			if( !(func->parameterTypes[n].GetTypeInfo()->flags & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY)) )
 			{
 				engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf());
-	
+
 				asCString str;
 				str.Format(TXT_CANNOT_PASS_TYPE_s_BY_VAL, func->parameterTypes[n].GetTypeInfo()->name.AddressOf());
 				engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
@@ -438,7 +450,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
 			// will be used depending on the memory layout of the object
 			// Ref: http://www.x86-64.org/documentation/abi.pdf
 			// Ref: http://www.agner.org/optimize/calling_conventions.pdf
-			if( 
+			if(
 #ifdef COMPLEX_OBJS_PASSED_BY_REF
 			    !(func->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK) &&
 #endif
@@ -553,7 +565,7 @@ int CallSystemFunction(int id, asCContext *context)
 //
 // Return value:
 //
-// The function should return the value that is returned in registers. 
+// The function should return the value that is returned in registers.
 asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2, void *secondObj);
 
 
@@ -573,9 +585,15 @@ int CallSystemFunction(int id, asCContext *context)
 	void    *retPointer        = 0;
 	int      popSize           = sysFunc->paramSize;
 
+	// TODO: clean-up: CallSystemFunctionNative should have two arguments for object pointers
+	//                 objForThiscall is the object pointer that should be used for the thiscall
+	//                 objForArg is the object pointer that should be passed as argument when using OBJFIRST or OBJLAST
+
+	// Used to save two object pointers with THISCALL_OBJLAST or THISCALL_OBJFIRST
+	void *obj = 0;
+	void *secondObj = 0;
+
 #ifdef AS_NO_THISCALL_FUNCTOR_METHOD
-	void    *obj               = 0;
-	void    *secondObj         = 0;
 
 	if( callConv >= ICC_THISCALL )
 	{
@@ -613,13 +631,6 @@ int CallSystemFunction(int id, asCContext *context)
 		}
 	}
 #else
-	// TODO: clean-up: CallSystemFunctionNative should have two arguments for object pointers
-	//                 objForThiscall is the object pointer that should be used for the thiscall
-	//                 objForArg is the object pointer that should be passed as argument when using OBJFIRST or OBJLAST
-
-	// Used to save two object pointers with THISCALL_OBJLAST or THISCALL_OBJFIRST
-	void *obj               = 0;
-	void *secondObj         = 0;
 
 	if( callConv >= ICC_THISCALL )
 	{
@@ -687,7 +698,7 @@ int CallSystemFunction(int id, asCContext *context)
 		popSize += AS_PTR_SIZE;
 		args += AS_PTR_SIZE;
 
-		// When returning the value on the location allocated by the called 
+		// When returning the value on the location allocated by the called
 		// we shouldn't set the object type in the register
 		context->m_regs.objectType = 0;
 	}
@@ -697,15 +708,22 @@ int CallSystemFunction(int id, asCContext *context)
 		context->m_regs.objectType = descr->returnType.GetTypeInfo();
 	}
 
+	// For composition we need to add the offset and/or dereference the pointer
+	if(obj)
+	{
+		obj = (void*) ((char*) obj + sysFunc->compositeOffset);
+		if(sysFunc->isCompositeIndirect) obj = *((void**)obj);
+	}
+
 	context->m_callingSystemFunction = descr;
 	bool cppException = false;
 #ifdef AS_NO_EXCEPTIONS
 	retQW = CallSystemFunctionNative(context, descr, obj, args, sysFunc->hostReturnInMemory ? retPointer : 0, retQW2, secondObj);
 #else
-	// This try/catch block is to catch potential exception that may 
+	// This try/catch block is to catch potential exception that may
 	// be thrown by the registered function. The implementation of the
 	// CallSystemFunctionNative() must make sure not to have any manual
-	// clean-up after the call to the real function, or that won't be 
+	// clean-up after the call to the real function, or that won't be
 	// executed in case of an exception.
 	try
 	{
@@ -715,9 +733,9 @@ int CallSystemFunction(int id, asCContext *context)
 	{
 		cppException = true;
 
-		// Convert the exception to a script exception so the VM can 
+		// Convert the exception to a script exception so the VM can
 		// properly report the error to the application and then clean up
-		context->SetException(TXT_EXCEPTION_CAUGHT);
+		context->HandleAppException();
 	}
 #endif
 	context->m_callingSystemFunction = 0;
@@ -774,8 +792,8 @@ int CallSystemFunction(int id, asCContext *context)
 
 			if( context->m_status == asEXECUTION_EXCEPTION && !cppException )
 			{
-				// If the function raised a script exception it really shouldn't have 
-				// initialized the object. However, as it is a soft exception there is 
+				// If the function raised a script exception it really shouldn't have
+				// initialized the object. However, as it is a soft exception there is
 				// no way for the application to not return a value, so instead we simply
 				// destroy it here, to pretend it was never created.
 				if(CastToObjectType(descr->returnType.GetTypeInfo())->beh.destruct )
@@ -868,14 +886,14 @@ int CallSystemFunction(int id, asCContext *context)
 					*addr = 0;
 				}
 			}
-			else 
+			else
 			{
 				asASSERT( clean->op == 1 || clean->op == 2 );
 				asASSERT( *addr );
 
 				if( clean->op == 2 )
 					engine->CallObjectMethod(*addr, clean->ot->beh.destruct);
-				
+
 				engine->CallFree(*addr);
 			}
 		}

+ 20 - 16
source/as_callfunc.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -59,7 +59,7 @@ int CallSystemFunction(int id, asCContext *context);
 
 inline asPWORD FuncPtrToUInt(asFUNCTION_t func)
 {
-	// A little trickery as the C++ standard doesn't allow direct 
+	// A little trickery as the C++ standard doesn't allow direct
 	// conversion between function pointer and data pointer
 	union { asFUNCTION_t func; asPWORD idx; } u;
 	u.func = func;
@@ -108,6 +108,8 @@ struct asSSystemFunctionInterface
 	bool                 takesObjByVal;
 	asCArray<bool>       paramAutoHandles; // TODO: Should be able to remove this array. Perhaps the flags can be stored together with the inOutFlags in asCScriptFunction?
 	bool                 returnAutoHandle;
+	int                  compositeOffset;
+	bool                 isCompositeIndirect;
 	void                *auxiliary; // can be used for functors, e.g. by asCALL_THISCALL_ASGLOBAL or asCALL_THISCALL_OBJFIRST
 
 	struct SClean
@@ -118,7 +120,7 @@ struct asSSystemFunctionInterface
 	};
 	asCArray<SClean>     cleanArgs;
 
-	asSSystemFunctionInterface() {}
+	asSSystemFunctionInterface() : func(0), baseOffset(0), callConv(ICC_GENERIC_FUNC), scriptReturnSize(0), hostReturnInMemory(false), hostReturnFloat(false), hostReturnSize(0), paramSize(0), takesObjByVal(false), returnAutoHandle(false), compositeOffset(0), isCompositeIndirect(false), auxiliary(0) {}
 
 	asSSystemFunctionInterface(const asSSystemFunctionInterface &in)
 	{
@@ -127,19 +129,21 @@ struct asSSystemFunctionInterface
 
 	asSSystemFunctionInterface &operator=(const asSSystemFunctionInterface &in)
 	{
-		func               = in.func;
-		baseOffset         = in.baseOffset;
-		callConv           = in.callConv;
-		scriptReturnSize   = in.scriptReturnSize;
-		hostReturnInMemory = in.hostReturnInMemory;
-		hostReturnFloat    = in.hostReturnFloat;
-		hostReturnSize     = in.hostReturnSize;
-		paramSize          = in.paramSize;
-		takesObjByVal      = in.takesObjByVal;
-		paramAutoHandles   = in.paramAutoHandles;
-		returnAutoHandle   = in.returnAutoHandle;
-		auxiliary          = in.auxiliary;
-		cleanArgs          = in.cleanArgs;
+		func                = in.func;
+		baseOffset          = in.baseOffset;
+		callConv            = in.callConv;
+		scriptReturnSize    = in.scriptReturnSize;
+		hostReturnInMemory  = in.hostReturnInMemory;
+		hostReturnFloat     = in.hostReturnFloat;
+		hostReturnSize      = in.hostReturnSize;
+		paramSize           = in.paramSize;
+		takesObjByVal       = in.takesObjByVal;
+		paramAutoHandles    = in.paramAutoHandles;
+		returnAutoHandle    = in.returnAutoHandle;
+		compositeOffset     = in.compositeOffset;
+		isCompositeIndirect = in.isCompositeIndirect;
+		auxiliary           = in.auxiliary;
+		cleanArgs           = in.cleanArgs;
 		return *this;
 	}
 };

+ 43 - 25
source/as_callfunc_x86.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -116,7 +116,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
 
 	int dpos = 1;
 
-	if( isThisCallMethod && 
+	if( isThisCallMethod &&
 		(callConv >= ICC_THISCALL_OBJFIRST &&
 		 callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) )
 	{
@@ -143,13 +143,13 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
 #endif
 				{
 					// Copy the object's memory to the buffer
-					// TODO: bug: Must call the object's copy constructor instead of doing a memcpy, 
-					//            as the object may hold a pointer to itself. It's not enough to 
+					// TODO: bug: Must call the object's copy constructor instead of doing a memcpy,
+					//            as the object may hold a pointer to itself. It's not enough to
 					//            change only this memcpy as the assembler routine also makes a copy
-					//            of paramBuffer to the final stack location. To avoid the second 
+					//            of paramBuffer to the final stack location. To avoid the second
 					//            copy the C++ routine should point paramBuffer to the final stack
 					//            position and copy the values directly to that location. The assembler
-					//            routines then don't need to copy anything, and will just be 
+					//            routines then don't need to copy anything, and will just be
 					//            responsible for setting up the registers and the stack frame appropriately.
 					memcpy(&paramBuffer[dpos], *(void**)(args+spos), descr->parameterTypes[n].GetSizeInMemoryBytes());
 
@@ -173,7 +173,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
 		args = &paramBuffer[1];
 	}
 
-	if( isThisCallMethod && 
+	if( isThisCallMethod &&
 		(callConv >= ICC_THISCALL_OBJLAST &&
 		 callConv <= ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM) )
 	{
@@ -349,11 +349,12 @@ endcopy:
 
 	asm __volatile__(
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -400,6 +401,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -471,11 +473,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -523,6 +526,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -594,11 +598,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -646,6 +651,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -726,11 +732,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -782,6 +789,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -858,11 +866,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -911,6 +920,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -989,11 +999,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -1045,6 +1056,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -1111,11 +1123,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -1160,6 +1173,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -1242,11 +1256,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -1300,6 +1315,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable
@@ -1389,11 +1405,12 @@ endcopy:
 
 	asm __volatile__ (
 #ifdef __OPTIMIZE__
-		// When compiled with optimizations the stack unwind doesn't work properly, 
+		// When compiled with optimizations the stack unwind doesn't work properly,
 		// causing exceptions to crash the application. By adding this prologue
-		// and the epilogue below, the stack unwind works as it should. 
+		// and the epilogue below, the stack unwind works as it should.
 		// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
 		"pushl %%ebp               \n"
+		".cfi_startproc            \n"
 		".cfi_adjust_cfa_offset 4  \n"
 		".cfi_rel_offset ebp, 0    \n"
 		"movl %%esp, %%ebp         \n"
@@ -1460,6 +1477,7 @@ endcopy:
 		"popl %%ebp                \n"
 		".cfi_adjust_cfa_offset -4 \n"
 		".cfi_restore ebp          \n"
+		".cfi_endproc              \n"
 #endif
 		// Copy EAX:EDX to retQW. As the stack pointer has been
 		// restored it is now safe to access the local variable

Разлика између датотеке није приказан због своје велике величине
+ 405 - 108
source/as_compiler.cpp


+ 33 - 5
source/as_compiler.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -100,7 +100,7 @@ struct asCExprValue
 	bool  isVariable : 1;
 	bool  isExplicitHandle : 1;
 	bool  isRefToLocal : 1; // The reference may be to a local variable
-	bool  isHandleSafe : 1; // the life-time of the handle is guaranteed for the duration of the access
+	bool  isRefSafe : 1; // the life-time of the ref is guaranteed for the duration of the access
 	short dummy : 9;
 	short stackOffset;
 
@@ -168,6 +168,7 @@ struct asCExprContext
 	// TODO: cleanup: use ambiguousName and an enum to say if it is a method, global func, or enum value
 	asCString methodName;
 	asCString enumValue;
+	asSNameSpace *symbolNamespace; // The namespace in which the ambigious symbol was found
 	bool isAnonymousInitList; // Set to true if the expression is an init list for which the type has not yet been determined
 };
 
@@ -262,7 +263,7 @@ protected:
 
 	void CompileInitList(asCExprValue *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem);
 	int  CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode, int &elementsInSubList);
-	int  CompilerAnonymousInitList(asCScriptNode *listNode, asCExprContext *ctx, const asCDataType &dt);
+	int  CompileAnonymousInitList(asCScriptNode *listNode, asCExprContext *ctx, const asCDataType &dt);
 
 	int  CallDefaultConstructor(const asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool derefDest = false);
 	int  CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false);
@@ -270,7 +271,7 @@ protected:
 	int  CompileArgumentList(asCScriptNode *node, asCArray<asCExprContext *> &args, asCArray<asSNamedArgument> &namedArgs);
 	int  CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray<asCExprContext*> &args, int funcId, asCObjectType *type, asCArray<asSNamedArgument> *namedArgs = 0);
 	asUINT MatchFunctions(asCArray<int> &funcs, asCArray<asCExprContext*> &args, asCScriptNode *node, const char *name, asCArray<asSNamedArgument> *namedArgs = NULL, asCObjectType *objectType = NULL, bool isConstMethod = false, bool silent = false, bool allowObjectConstruct = true, const asCString &scope = "");
-	int  CompileVariableAccess(const asCString &name, const asCString &scope, asCExprContext *ctx, asCScriptNode *errNode, bool isOptional = false, bool noFunction = false, bool noGlobal = false, asCObjectType *objType = 0);
+	int  CompileVariableAccess(const asCString &name, const asCString &scope, asCExprContext *ctx, asCScriptNode *errNode, bool isOptional = false, asCObjectType *objType = 0);
 	void CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults);
 	bool CompileAutoType(asCDataType &autoType, asCExprContext &compiledCtx, asCScriptNode *exprNode, asCScriptNode *errNode);
 	bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, const asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asCExprContext *preCompiled = 0);
@@ -315,6 +316,29 @@ protected:
 	asSNameSpace *DetermineNameSpace(const asCString &scope);
 	int  SetupParametersAndReturnVariable(asCArray<asCString> &parameterNames, asCScriptNode *func);
 
+	enum SYMBOLTYPE
+	{
+		SL_NOMATCH,
+		SL_LOCALCONST,
+		SL_LOCALVAR,
+		SL_THISPTR,
+		SL_CLASSPROPACCESS,
+		SL_CLASSPROP,
+		SL_CLASSMETHOD,
+		SL_CLASSTYPE,
+		SL_GLOBALPROPACCESS,
+		SL_GLOBALCONST,
+		SL_GLOBALVAR,
+		SL_GLOBALFUNC,
+		SL_GLOBALTYPE,
+		SL_ENUMVAL,
+		SL_ERROR = -1
+	};
+
+	SYMBOLTYPE SymbolLookup(const asCString &name, const asCString &scope, asCObjectType *objType, asCExprContext *outResult);
+	SYMBOLTYPE SymbolLookupLocalVar(const asCString &name, asCExprContext *outResult);
+	SYMBOLTYPE SymbolLookupMember(const asCString &name, asCObjectType *objType, asCExprContext *outResult);
+
 	void DetermineSingleFunc(asCExprContext *ctx, asCScriptNode *node);
 
 	// Returns the cost of the conversion (the sum of the EConvCost performed)
@@ -363,7 +387,7 @@ protected:
 	asCArray<int> breakLabels;
 	asCArray<int> continueLabels;
 
-	int AllocateVariable(const asCDataType &type, bool isTemporary, bool forceOnHeap = false);
+	int AllocateVariable(const asCDataType &type, bool isTemporary, bool forceOnHeap = false, bool asReference = false);
 	int AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asCExprContext *ctx);
 	int GetVariableOffset(int varIndex);
 	int GetVariableSlot(int varOffset);
@@ -393,6 +417,10 @@ protected:
 	// This array holds the indices of variables that must not be used in an allocation
 	asCArray<int>         reservedVariables;
 
+	// This array holds the string constants that were allocated during the compilation, 
+	// so they can be released upon completion, whether the compilation was successful or not.
+	asCArray<void*>       usedStringConstants;
+
 	bool isCompilingDefaultArg;
 	bool isProcessingDeferredParams;
 	int  noCodeOutput;

+ 72 - 60
source/as_config.h

@@ -607,7 +607,8 @@
 
 // GNU C (and MinGW or Cygwin on Windows)
 // Use the following command to determine predefined macros: echo . | g++ -dM -E -
-#if (defined(__GNUC__) && !defined(__SNC__)) || defined(EPPC) || defined(__CYGWIN__) // JWC -- use this instead for Wii
+// MSVC2015 can now use CLang too, but it shouldn't go in here
+#if (defined(__GNUC__) && !defined(__SNC__) && !defined(_MSC_VER)) || defined(EPPC) || defined(__CYGWIN__) // JWC -- use this instead for Wii
 	#define GNU_STYLE_VIRTUAL_METHOD
 	#define MULTI_BASE_OFFSET(x) (*((asPWORD*)(&x)+1))
 	#define asVSNPRINTF(a, b, c, d) vsnprintf(a, b, c, d)
@@ -804,13 +805,12 @@
 
 			// As of version 4.7 MinGW changed the ABI, presumably
 			// to be better aligned with how MSVC works
-			// Urho3D: also check for Clang version and use the same workaround
 			#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || __GNUC__ > 4
 				#define AS_MINGW47
 			#endif
 
-			#if (__clang_major__ == 3 && __clang_minor__ > 4)
-			    #define AS_MINGW47
+			#if (__clang_major__ == 3 && __clang_minor__ > 4) || __clang_major > 3
+				#define AS_MINGW47
 			#endif
 
 			#ifdef AS_MINGW47
@@ -842,6 +842,7 @@
 		#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
 
 		#if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
+			// x86 32bit
 			#define THISCALL_RETURN_SIMPLE_IN_MEMORY
 			#define CDECL_RETURN_SIMPLE_IN_MEMORY
 			#define STDCALL_RETURN_SIMPLE_IN_MEMORY
@@ -850,9 +851,8 @@
 			#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
 			#define AS_X86
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
-
-		// Urho3D - use __aarch64__ instead of __arm64__ because GCC only emits the former
-		#elif defined(__LP64__) && !defined(__aarch64__)
+		#elif defined(__x86_64__)
+			// x86 64bit
 			#define AS_X64_GCC
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
 			#define HAS_128_BIT_PRIMITIVES
@@ -862,60 +862,68 @@
 			// STDCALL is not available on 64bit Linux
 			#undef STDCALL
 			#define STDCALL
+		#elif defined(__ARMEL__) || defined(__arm__) || defined(__aarch64__) || defined(__AARCH64EL__)
+			// arm
 
-		// Urho3D - Add support for aarch64-linux-gnu
-		#elif defined(__aarch64__)
-			// AngelScript currently doesn't support native calling
-			// for 64bit ARM processors so it's necessary to turn on
-			// portability mode
-			#define AS_MAX_PORTABILITY
-			// STDCALL is not available on ARM
-			#undef STDCALL
-			#define STDCALL
+			// The assembler code currently doesn't support arm v4, nor 64bit (v8)
+			#if !defined(__ARM_ARCH_4__) && !defined(__ARM_ARCH_4T__) && !defined(__LP64__)
+				#define AS_ARM
 
-		#elif (defined(__ARMEL__) || defined(__arm__)) && !(defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__))
-			#define AS_ARM
+				// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
+				#define AS_NO_EXCEPTIONS
 
-			// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
-			#define AS_NO_EXCEPTIONS
+				#undef STDCALL
+				#define STDCALL
 
-			#undef STDCALL
-			#define STDCALL
+				#define CDECL_RETURN_SIMPLE_IN_MEMORY
+				#define STDCALL_RETURN_SIMPLE_IN_MEMORY
+				#define THISCALL_RETURN_SIMPLE_IN_MEMORY
 
-			#define CDECL_RETURN_SIMPLE_IN_MEMORY
-			#define STDCALL_RETURN_SIMPLE_IN_MEMORY
-			#define THISCALL_RETURN_SIMPLE_IN_MEMORY
+				#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
+				#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
+				#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 
-			#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
-			#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
-			#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
+				#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
+				#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
+				#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
 
-			#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
-			#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
-			#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
+				#ifndef AS_MAX_PORTABILITY
+				// Make a few checks against incompatible ABI combinations
+				#if defined(__FAST_MATH__) && __FAST_MATH__ == 1
+					#error -ffast-math is not supported with native calling conventions
+				#endif
+				#endif
 
-			#ifndef AS_MAX_PORTABILITY
-			// Make a few checks against incompatible ABI combinations
-			#if defined(__FAST_MATH__) && __FAST_MATH__ == 1
-				#error -ffast-math is not supported with native calling conventions
-			#endif
-			#endif
+				// Verify if soft-float or hard-float ABI is used
+				#if defined(__SOFTFP__) && __SOFTFP__ == 1
+					// -ffloat-abi=softfp or -ffloat-abi=soft
+					#define AS_SOFTFP
+				#endif
 
-			// Verify if soft-float or hard-float ABI is used
-			#if defined(__SOFTFP__) && __SOFTFP__ == 1
-				// -ffloat-abi=softfp or -ffloat-abi=soft
-				#define AS_SOFTFP
-			#endif
+				// Tested with both hard float and soft float abi
+				#undef AS_NO_THISCALL_FUNCTOR_METHOD
 
-			// Tested with both hard float and soft float abi
-			#undef AS_NO_THISCALL_FUNCTOR_METHOD
+            // Urho3D - Add support for aarch64-linux-gnu
+            #elif defined(__aarch64__)
+                // arm64
+
+                // AngelScript currently doesn't support native calling
+                // for 64bit ARM processors so it's necessary to turn on
+                // portability mode
+                #define AS_MAX_PORTABILITY
+                // STDCALL is not available on ARM
+                #undef STDCALL
+                #define STDCALL
+			#endif
 
 		#elif defined(__mips__)
+			// mips
 			#define AS_MIPS
 			#undef STDCALL
 			#define STDCALL
 
 			#ifdef _ABIO32
+				// 32bit O32 ABI
 				#define AS_MIPS
 
 				// All structures are returned in memory regardless of size or complexity
@@ -930,6 +938,13 @@
 				// For other ABIs the native calling convention is not available (yet)
 				#define AS_MAX_PORTABILITY
 			#endif
+		#elif defined(__PPC64__)
+			// PPC 64bit
+
+			// The code in as_callfunc_ppc_64.cpp was built for PS3 and XBox 360, that
+			// although use 64bit PPC only uses 32bit pointers.
+			// TODO: Add support for native calling conventions on Linux with PPC 64bit
+			#define AS_MAX_PORTABILITY
 		#else
 			#define AS_MAX_PORTABILITY
 		#endif
@@ -1130,7 +1145,7 @@
 			// Support native calling conventions on Intel 32bit CPU
 			#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
 			#define AS_X86
-		#elif (defined(__x86_64__) || defined(__LP64__))
+		#elif defined(__x86_64__)
 			#define AS_X64_GCC
 			#define HAS_128_BIT_PRIMITIVES
 			#define SPLIT_OBJS_BY_MEMBER_TYPES
@@ -1190,23 +1205,20 @@
 // Detect target hardware
 //------------------------------------------------
 
-// X86, Intel, AMD, etc, i.e. most PCs
-#if defined(__i386__) || defined(_M_IX86)
-	// Nothing special here
-#endif
-
-// PowerPC, e.g. Mac, GameCube, PS3, XBox 360, Wii
-#if defined(__PPC__) || defined(__ppc__) || defined(_PPC_) || defined(EPPC)
-	#define AS_BIG_ENDIAN
-
-	// Gamecube
-	#if defined(_GC)
-		#define AS_USE_DOUBLE_AS_FLOAT
-	#endif
+// Big endian CPU target?
+// see: http://sourceforge.net/p/predef/wiki/Endianness/
+#if !defined(AS_BIG_ENDIAN) && \
+	defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
+	defined(__BIG_ENDIAN__) || \
+	defined(__ARMEB__) || \
+	defined(__THUMBEB__) || \
+	defined(__AARCH64EB__) || \
+	defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
+		#define AS_BIG_ENDIAN
 #endif
 
-// Dreamcast console
-#ifdef __SH4_SINGLE_ONLY__
+// Dreamcast and Gamecube use only 32bit floats, so treat doubles as floats
+#if defined(__SH4_SINGLE_ONLY__) || defined(_GC)
 	#define AS_USE_DOUBLE_AS_FLOAT	// use 32bit floats instead of doubles
 #endif
 

+ 1 - 3
source/as_configgroup.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -143,8 +143,6 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed)
 		if( index >= 0 )
 			engine->registeredGlobalFuncs.Erase(index);
 		scriptFunctions[n]->ReleaseInternal();
-		if( engine->stringFactory == scriptFunctions[n] )
-			engine->stringFactory = 0;
 	}
 	scriptFunctions.SetLength(0);
 

+ 53 - 33
source/as_context.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -28,7 +28,6 @@
    [email protected]
 */
 
-// Modified by Nathanial Lydick for Urho3D
 
 //
 // as_context.cpp
@@ -167,6 +166,7 @@ asCThreadLocalData *asPushActiveContext(asIScriptContext *ctx)
 // internal
 void asPopActiveContext(asCThreadLocalData *tld, asIScriptContext *ctx)
 {
+	UNUSED_VAR(ctx);
 	asASSERT(tld && tld->activeContexts[tld->activeContexts.GetLength() - 1] == ctx);
 	if (tld)
 		tld->activeContexts.PopLast();
@@ -374,7 +374,7 @@ int asCContext::Prepare(asIScriptFunction *func)
 	if( func == 0 )
 	{
 		asCString str;
-		str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_d, "Prepare", "null", asNO_FUNCTION);
+		str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_s_d, "Prepare", "null", errorNames[-asNO_FUNCTION], asNO_FUNCTION);
 		m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
 		return asNO_FUNCTION;
 	}
@@ -382,7 +382,7 @@ int asCContext::Prepare(asIScriptFunction *func)
 	if( m_status == asEXECUTION_ACTIVE || m_status == asEXECUTION_SUSPENDED )
 	{
 		asCString str;
-		str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_d, "Prepare", func->GetDeclaration(true, true), asCONTEXT_ACTIVE);
+		str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_s_d, "Prepare", func->GetDeclaration(true, true), errorNames[-asCONTEXT_ACTIVE], asCONTEXT_ACTIVE);
 		m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
 		return asCONTEXT_ACTIVE;
 	}
@@ -424,7 +424,7 @@ int asCContext::Prepare(asIScriptFunction *func)
 		if( m_engine != func->GetEngine() )
 		{
 			asCString str;
-			str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_d, "Prepare", func->GetDeclaration(true, true), asINVALID_ARG);
+			str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_s_d, "Prepare", func->GetDeclaration(true, true), errorNames[-asINVALID_ARG], asINVALID_ARG);
 			m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
 			return asINVALID_ARG;
 		}
@@ -509,6 +509,11 @@ int asCContext::Unprepare()
 	if( m_status == asEXECUTION_ACTIVE || m_status == asEXECUTION_SUSPENDED )
 		return asCONTEXT_ACTIVE;
 
+	// Set the context as active so that any clean up code can use access it if desired
+	asCThreadLocalData *tld = asPushActiveContext((asIScriptContext *)this);
+	asDWORD count = m_refCount.get();
+	UNUSED_VAR(count);
+
 	// Only clean the stack if the context was prepared but not executed until the end
 	if( m_status != asEXECUTION_UNINITIALIZED &&
 		m_status != asEXECUTION_FINISHED )
@@ -519,6 +524,11 @@ int asCContext::Unprepare()
 	// Release the returned object (if any)
 	CleanReturnObject();
 
+	// TODO: Unprepare is called during destruction, so nobody
+	//       must be allowed to keep an extra reference
+	asASSERT(m_refCount.get() == count);
+	asPopActiveContext(tld, this);
+
 	// Release the object if it is a script object
 	if( m_initialFunction && m_initialFunction->objectType && (m_initialFunction->objectType->flags & asOBJ_SCRIPT_OBJECT) )
 	{
@@ -1190,7 +1200,7 @@ int asCContext::Execute()
 	if( m_status != asEXECUTION_SUSPENDED && m_status != asEXECUTION_PREPARED )
 	{
 		asCString str;
-		str.Format(TXT_FAILED_IN_FUNC_s_d, "Execute", asCONTEXT_NOT_PREPARED);
+		str.Format(TXT_FAILED_IN_FUNC_s_s_d, "Execute", errorNames[-asCONTEXT_NOT_PREPARED], asCONTEXT_NOT_PREPARED);
 		m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
 		return asCONTEXT_NOT_PREPARED;
 	}
@@ -2496,18 +2506,9 @@ void asCContext::ExecuteNext()
 		break;
 
 	case asBC_STR:
-		{
-			// Get the string id from the argument
-			asWORD w = asBC_WORDARG0(l_bc);
-			// Push the string pointer on the stack
-			const asCString &b = m_engine->GetConstantString(w);
-			l_sp -= AS_PTR_SIZE;
-			*(asPWORD*)l_sp = (asPWORD)b.AddressOf();
-			// Push the string length on the stack
-			--l_sp;
-			*l_sp = (asDWORD)b.GetLength();
-			l_bc++;
-		}
+		// TODO: NEWSTRING: Deprecate this instruction
+		asASSERT(false);
+		l_bc++;
 		break;
 
 	case asBC_CALLSYS:
@@ -2849,10 +2850,10 @@ void asCContext::ExecuteNext()
 			if( !(objType->flags & asOBJ_NOCOUNT) )
 			{
 				// Release previous object held by destination pointer
-				if( *d != 0 )
+				if( *d != 0 && beh->release )
 					m_engine->CallObjectMethod(*d, beh->release);
 				// Increase ref counter of wanted object
-				if( s != 0 )
+				if( s != 0 && beh->addref )
 					m_engine->CallObjectMethod(s, beh->addref);
 			}
 
@@ -4108,10 +4109,10 @@ void asCContext::ExecuteNext()
 			if( !(objType->flags & asOBJ_NOCOUNT) )
 			{
 				// Release previous object held by destination pointer
-				if( *d != 0 )
+				if( *d != 0 && beh->release )
 					m_engine->CallObjectMethod(*d, beh->release);
 				// Increase ref counter of wanted object
-				if( s != 0 )
+				if( s != 0 && beh->addref )
 					m_engine->CallObjectMethod(s, beh->addref);
 			}
 
@@ -5113,6 +5114,26 @@ void asCContext::CallExceptionCallback()
 		m_engine->CallObjectMethod(m_exceptionCallbackObj, this, &m_exceptionCallbackFunc, 0);
 }
 
+#ifndef AS_NO_EXCEPTIONS
+// internal
+void asCContext::HandleAppException()
+{
+	// This method is called from within a catch(...) block
+	if (m_engine->translateExceptionCallback)
+	{
+		// Allow the application to translate the application exception to a proper exception string
+		if (m_engine->translateExceptionCallbackFunc.callConv < ICC_THISCALL)
+			m_engine->CallGlobalFunction(this, m_engine->translateExceptionCallbackObj, &m_engine->translateExceptionCallbackFunc, 0);
+		else
+			m_engine->CallObjectMethod(m_engine->translateExceptionCallbackObj, this, &m_engine->translateExceptionCallbackFunc, 0);
+	}
+
+	// Make sure an exception is set even if the application decides not to do any specific translation
+	if( m_status != asEXECUTION_EXCEPTION )
+		SetException(TXT_EXCEPTION_CAUGHT);
+}
+#endif
+
 // interface
 void asCContext::ClearLineCallback()
 {
@@ -5178,7 +5199,7 @@ int asCContext::CallGeneric(asCScriptFunction *descr)
 	{
 		// Convert the exception to a script exception so the VM can 
 		// properly report the error to the application and then clean up
-		SetException(TXT_EXCEPTION_CAUGHT);
+		HandleAppException();
 	}
 #endif
 	m_callingSystemFunction = 0;
@@ -5187,14 +5208,13 @@ int asCContext::CallGeneric(asCScriptFunction *descr)
 	m_regs.objectRegister = gen.objectRegister;
 	m_regs.objectType = descr->returnType.GetTypeInfo();
 
-	// Urho3D: add autohandle support
-	// based on http://www.gamedev.net/topic/630414-autohandles-with-generic-callconv/
-	if ( descr->returnType.IsObject()
-			&& !descr->returnType.IsReference()
-			&& descr->returnType.IsObjectHandle()
-			&& sysFunc->returnAutoHandle
-			&& m_regs.objectRegister )
-			m_engine->AddRefScriptObject(m_regs.objectRegister, descr->returnType.GetTypeInfo());
+	// Increase the returned handle if the function has been declared with autohandles
+	// and the engine is not set to use the old mode for the generic calling convention
+	if (sysFunc->returnAutoHandle && m_engine->ep.genericCallMode == 1 && m_regs.objectRegister)
+	{
+		asASSERT(!(descr->returnType.GetTypeInfo()->flags & asOBJ_NOCOUNT));
+		m_engine->CallObjectMethod(m_regs.objectRegister, CastToObjectType(descr->returnType.GetTypeInfo())->beh.addref);
+	}
 
 	// Clean up arguments
 	const asUINT cleanCount = sysFunc->cleanArgs.GetLength();
@@ -5368,7 +5388,7 @@ void *asCContext::GetAddressOfVar(asUINT varIndex, asUINT stackLevel)
 }
 
 // interface
-// returns the typeId of the 'this' object at the given call stack level (-1 for current)
+// returns the typeId of the 'this' object at the given call stack level (0 for current)
 // returns 0 if the function call at the given stack level is not a method
 int asCContext::GetThisTypeId(asUINT stackLevel)
 {
@@ -5386,7 +5406,7 @@ int asCContext::GetThisTypeId(asUINT stackLevel)
 }
 
 // interface
-// returns the 'this' object pointer at the given call stack level (-1 for current)
+// returns the 'this' object pointer at the given call stack level (0 for current)
 // returns 0 if the function call at the given stack level is not a method
 void *asCContext::GetThisPointer(asUINT stackLevel)
 {

+ 4 - 2
source/as_context.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2014 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -138,7 +138,9 @@ public:
 	void CallExceptionCallback();
 
 	int  CallGeneric(asCScriptFunction *func);
-
+#ifndef AS_NO_EXCEPTIONS
+	void HandleAppException();
+#endif
 	void DetachEngine();
 
 	void ExecuteNext();

+ 7 - 8
source/as_datatype.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -395,15 +395,14 @@ bool asCDataType::CanBeCopied() const
 	// It must be possible to instantiate the type
 	if( !CanBeInstantiated() ) return false;
 
-	// It must have a default constructor or factory
+	// It must have a default constructor or factory and the opAssign
+	// Alternatively it must have the copy constructor
 	asCObjectType *ot = CastToObjectType(typeInfo);
-	if( ot && ot->beh.construct == 0 &&
-		ot->beh.factory == 0 ) return false;
-
-	// It must be possible to copy the type
-	if( ot && ot->beh.copy == 0 ) return false;
+	if (ot && (((ot->beh.construct != 0 || ot->beh.factory != 0) && ot->beh.copy != 0) || 
+		       (ot->beh.copyconstruct != 0 || ot->beh.copyfactory != 0)) )
+		return true;
 
-	return true;
+	return false;
 }
 
 bool asCDataType::IsReadOnly() const

+ 23 - 1
source/as_gc.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -60,6 +60,9 @@ asCGarbageCollector::asCGarbageCollector()
 	seqAtSweepStart[0] = 0;
 	seqAtSweepStart[1] = 0;
 	seqAtSweepStart[2] = 0;
+
+	circularRefDetectCallbackFunc  = 0;
+	circularRefDetectCallbackParam = 0;
 }
 
 asCGarbageCollector::~asCGarbageCollector()
@@ -857,6 +860,25 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 		{
 			gcMap.MoveFirst(&gcMapCursor);
 			detectState = breakCircles_loop;
+
+			// If the application has requested a callback for detected circular references,
+			// then make that callback now for all the objects in the list. This step is not
+			// done in incremental steps as it is only meant for debugging purposes and thus
+			// doesn't require interactivity
+			if (gcMapCursor && circularRefDetectCallbackFunc)
+			{
+				while (gcMapCursor)
+				{
+					void *gcObj = gcMap.GetKey(gcMapCursor);
+					asCObjectType *type = gcMap.GetValue(gcMapCursor).type;
+					circularRefDetectCallbackFunc(type, gcObj, circularRefDetectCallbackParam);
+
+					gcMap.MoveNext(&gcMapCursor, gcMapCursor);
+				}
+
+				// Reset iterator
+				gcMap.MoveFirst(&gcMapCursor);
+			}
 		}
 		break;
 

+ 5 - 1
source/as_gc.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -66,6 +66,10 @@ public:
 
 	asCScriptEngine *engine;
 
+	// Callback for when circular reference are detected
+	asCIRCULARREFFUNC_t circularRefDetectCallbackFunc;
+	void *              circularRefDetectCallbackParam;
+
 protected:
 	struct asSObjTypePair {void *obj; asCObjectType *type; asUINT seqNbr;};
 	struct asSIntTypePair {int i; asCObjectType *type;};

+ 85 - 110
source/as_module.cpp

@@ -1,24 +1,24 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -67,7 +67,7 @@ asCModule::~asCModule()
 {
 	InternalReset();
 
-	// The builder is not removed by InternalReset because it holds the script 
+	// The builder is not removed by InternalReset because it holds the script
 	// sections that will be built, so we need to explictly remove it now if it exists
 	if( builder )
 	{
@@ -111,7 +111,7 @@ void asCModule::Discard()
 	asCScriptEngine *lEngine = engine;
 
 	// Instead of deleting the module immediately, move it to the discarded pile
-	// This will turn it invisible to the application, yet keep it alive until all 
+	// This will turn it invisible to the application, yet keep it alive until all
 	// external references to its entities have been released.
 	ACQUIREEXCLUSIVE(engine->engineRWLock);
 	if( lEngine->lastModule == this )
@@ -287,7 +287,7 @@ int asCModule::Build()
 #else
 	TimeIt("asCModule::Build");
 
-	// Don't allow the module to be rebuilt if there are still 
+	// Don't allow the module to be rebuilt if there are still
 	// external references that will need the previous code
 	// TODO: interface: The asIScriptModule must have a method for querying if the module is used
 	if( HasExternalReferences(false) )
@@ -322,7 +322,7 @@ int asCModule::Build()
 	r = builder->Build();
 	asDELETE(builder,asCBuilder);
 	builder = 0;
-	
+
 	if( r < 0 )
 	{
 		// Reset module again
@@ -359,7 +359,7 @@ int asCModule::Build()
 // interface
 int asCModule::ResetGlobalVars(asIScriptContext *ctx)
 {
-	if( isGlobalVarInitialized ) 
+	if( isGlobalVarInitialized )
 		CallExit();
 
 	return CallInit(ctx);
@@ -374,7 +374,7 @@ asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const
 // internal
 int asCModule::CallInit(asIScriptContext *myCtx)
 {
-	if( isGlobalVarInitialized ) 
+	if( isGlobalVarInitialized )
 		return asERROR;
 
 	// Each global variable needs to be cleared individually
@@ -414,19 +414,19 @@ int asCModule::CallInit(asIScriptContext *myCtx)
 					asCScriptFunction *func = desc->GetInitFunc();
 
 					engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "",
-										 func->GetLineNumber(0, 0) & 0xFFFFF, 
+										 func->GetLineNumber(0, 0) & 0xFFFFF,
 										 func->GetLineNumber(0, 0) >> 20,
 										 asMSGTYPE_ERROR,
 										 msg.AddressOf());
-										 
+
 					if( r == asEXECUTION_EXCEPTION )
 					{
 						const asIScriptFunction *function = ctx->GetExceptionFunction();
 
 						msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration());
 
-						engine->WriteMessage(function->GetScriptSectionName(), 
-											 ctx->GetExceptionLineNumber(), 
+						engine->WriteMessage(function->GetScriptSectionName(),
+											 ctx->GetExceptionLineNumber(),
 											 0,
 											 asMSGTYPE_INFORMATION,
 											 msg.AddressOf());
@@ -442,9 +442,9 @@ int asCModule::CallInit(asIScriptContext *myCtx)
 		ctx = 0;
 	}
 
-	// Even if the initialization failed we need to set the 
+	// Even if the initialization failed we need to set the
 	// flag that the variables have been initialized, otherwise
-	// the module won't free those variables that really were 
+	// the module won't free those variables that really were
 	// initialized.
 	isGlobalVarInitialized = true;
 
@@ -514,9 +514,9 @@ void asCModule::CallExit()
 // internal
 bool asCModule::HasExternalReferences(bool shuttingDown)
 {
-	// Check all entiteis in the module for any external references.
+	// Check all entities in the module for any external references.
 	// If there are any external references the module cannot be deleted yet.
-	
+
 	asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
 	while (it)
 	{
@@ -540,10 +540,16 @@ bool asCModule::HasExternalReferences(bool shuttingDown)
 		it++;
 	}
 
-	for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
-		if( scriptFunctions[n] && scriptFunctions[n]->externalRefCount.get() )
+	for (asUINT n = 0; n < scriptFunctions.GetLength(); n++)
+	{
+		asCScriptFunction *func = scriptFunctions[n];
+		if (func && func->externalRefCount.get())
 		{
-			if( !shuttingDown )
+			// If the func is shared and can be moved to another module then this is not a reason to keep the module alive
+			if (func->IsShared() && engine->FindNewOwnerForSharedFunc(func, this) != this)
+				continue;
+
+			if (!shuttingDown)
 				return true;
 			else
 			{
@@ -555,11 +561,18 @@ bool asCModule::HasExternalReferences(bool shuttingDown)
 				engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
 			}
 		}
+	}
 
-	for( asUINT n = 0; n < classTypes.GetLength(); n++ )
-		if( classTypes[n] && classTypes[n]->externalRefCount.get() )
+	for (asUINT n = 0; n < classTypes.GetLength(); n++)
+	{
+		asCObjectType *obj = classTypes[n];
+		if (obj && obj->externalRefCount.get())
 		{
-			if( !shuttingDown )
+			// If the obj is shared and can be moved to another module then this is not a reason to keep the module alive
+			if (obj->IsShared() && engine->FindNewOwnerForSharedType(obj, this) != this)
+				continue;
+
+			if (!shuttingDown)
 				return true;
 			else
 			{
@@ -571,11 +584,18 @@ bool asCModule::HasExternalReferences(bool shuttingDown)
 				engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
 			}
 		}
+	}
 
-	for( asUINT n = 0; n < funcDefs.GetLength(); n++ )
-		if( funcDefs[n] && funcDefs[n]->externalRefCount.get() )
+	for (asUINT n = 0; n < funcDefs.GetLength(); n++)
+	{
+		asCFuncdefType *func = funcDefs[n];
+		if (func && func->externalRefCount.get())
 		{
-			if( !shuttingDown )
+			// If the funcdef is shared and can be moved to another module then this is not a reason to keep the module alive
+			if (func->IsShared() && engine->FindNewOwnerForSharedType(func, this) != this)
+				continue;
+
+			if (!shuttingDown)
 				return true;
 			else
 			{
@@ -587,11 +607,18 @@ bool asCModule::HasExternalReferences(bool shuttingDown)
 				engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
 			}
 		}
+	}
 
-	for( asUINT n = 0; n < templateInstances.GetLength(); n++ )
-		if( templateInstances[n] && templateInstances[n]->externalRefCount.get() )
+	for (asUINT n = 0; n < templateInstances.GetLength(); n++)
+	{
+		asCObjectType *obj = templateInstances[n];
+		if (obj && obj->externalRefCount.get())
 		{
-			if( !shuttingDown )
+			// If the template can be moved to another module then this is not a reason to keep the module alive
+			if (obj->IsShared() && engine->FindNewOwnerForSharedType(obj, this) != this)
+				continue;
+
+			if (!shuttingDown)
 				return true;
 			else
 			{
@@ -603,6 +630,7 @@ bool asCModule::HasExternalReferences(bool shuttingDown)
 				engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
 			}
 		}
+	}
 
 	return false;
 }
@@ -617,7 +645,7 @@ void asCModule::InternalReset()
 	// Remove all global functions
 	globalFunctions.Clear();
 
-	// Destroy the internals of the global properties here, but do not yet remove them from the 
+	// Destroy the internals of the global properties here, but do not yet remove them from the
 	// engine, because functions need the engine's varAddressMap to get to the property. If the
 	// property is removed already, it may leak as the refCount doesn't reach 0.
 	asCSymbolTableIterator<asCGlobalProperty> globIt = scriptGlobals.List();
@@ -829,7 +857,7 @@ int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
 	int id = -1;
 	for( asUINT n = 0; n < bindInformations.GetLength(); ++n )
 	{
-		if( func.name == bindInformations[n]->importedFunctionSignature->name && 
+		if( func.name == bindInformations[n]->importedFunctionSignature->name &&
 			func.returnType == bindInformations[n]->importedFunctionSignature->returnType &&
 			func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
 		{
@@ -965,7 +993,7 @@ int asCModule::RemoveGlobalVar(asUINT index)
 	// then uninitialize the variable before it is removed
 	if (isGlobalVarInitialized)
 		UninitializeGlobalProp(prop);
-	
+
 	// Destroy the internal of the global variable (removes the initialization function)
 	prop->DestroyInternal();
 
@@ -1014,7 +1042,7 @@ int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
 void *asCModule::GetAddressOfGlobalVar(asUINT index)
 {
 	asCGlobalProperty *prop = scriptGlobals.Get(index);
-	if( !prop ) 
+	if( !prop )
 		return 0;
 
 	// For object variables it's necessary to dereference the pointer to get the address of the value
@@ -1065,25 +1093,15 @@ asUINT asCModule::GetObjectTypeCount() const
 	return (asUINT)classTypes.GetLength();
 }
 
-// interface 
+// interface
 asITypeInfo *asCModule::GetObjectTypeByIndex(asUINT index) const
 {
-	if( index >= classTypes.GetLength() ) 
+	if( index >= classTypes.GetLength() )
 		return 0;
 
 	return classTypes[index];
 }
 
-#ifdef AS_DEPRECATED
-// Deprecated since 2.31.0, 2015-12-06
-// interface
-asITypeInfo *asCModule::GetObjectTypeByName(const char *in_name) const
-{
-	asITypeInfo *ti = GetTypeInfoByName(in_name);
-	return CastToObjectType(reinterpret_cast<asCTypeInfo*>(ti));
-}
-#endif
-
 // interface
 asITypeInfo *asCModule::GetTypeInfoByName(const char *in_name) const
 {
@@ -1139,16 +1157,6 @@ int asCModule::GetTypeIdByDecl(const char *decl) const
 	return engine->GetTypeIdFromDataType(dt);
 }
 
-#ifdef AS_DEPRECATED
-// Deprecated since 2.31.0, 2015-12-06
-// interface
-asITypeInfo *asCModule::GetObjectTypeByDecl(const char *decl) const
-{
-	asITypeInfo *ti = GetTypeInfoByDecl(decl);
-	return CastToObjectType(reinterpret_cast<asCTypeInfo*>(ti));
-}
-#endif
-
 // interface
 asITypeInfo *asCModule::GetTypeInfoByDecl(const char *decl) const
 {
@@ -1182,34 +1190,6 @@ asITypeInfo *asCModule::GetEnumByIndex(asUINT index) const
 	return enumTypes[index];
 }
 
-#ifdef AS_DEPRECATED
-// Deprecated since 2.31.0, 2015-12-06
-// interface
-int asCModule::GetEnumValueCount(int enumTypeId) const
-{
-	asITypeInfo *ti = engine->GetTypeInfoById(enumTypeId);
-	asCEnumType *e = CastToEnumType(reinterpret_cast<asCTypeInfo*>(ti));
-	if (e == 0)
-		return asINVALID_TYPE;
-
-	return e->GetEnumValueCount();
-}
-#endif
-
-#ifdef AS_DEPRECATED
-// Deprecated since 2.31.0, 2015-12-06
-// interface
-const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
-{
-	asITypeInfo *ti = engine->GetTypeInfoById(enumTypeId);
-	asCEnumType *e = CastToEnumType(reinterpret_cast<asCTypeInfo*>(ti));
-	if (e == 0)
-		return 0;
-
-	return e->GetEnumValueByIndex(index, outValue);
-}
-#endif
-
 // interface
 asUINT asCModule::GetTypedefCount() const
 {
@@ -1237,7 +1217,7 @@ int asCModule::GetNextImportedFunctionId()
 
 #ifndef AS_NO_COMPILER
 // internal
-int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &funcName, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isProtected, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns)
+int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &funcName, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isGlobalFunction, asSFunctionTraits funcTraits, asSNameSpace *ns)
 {
 	asASSERT(id >= 0);
 
@@ -1258,7 +1238,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
 
 	// All methods of shared objects are also shared
 	if( objType && objType->IsShared() )
-		isShared = true;
+		funcTraits.SetTrait(asTRAIT_SHARED, true);
 
 	func->name             = funcName;
 	func->nameSpace        = ns;
@@ -1276,18 +1256,13 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
 	func->objectType       = objType;
 	if( objType )
 		objType->AddRefInternal();
-	func->isReadOnly       = isConstMethod;
-	func->isPrivate        = isPrivate;
-	func->isProtected      = isProtected;
-	func->isFinal          = isFinal;
-	func->isOverride       = isOverride;
-	func->isShared         = isShared;
+	func->traits           = funcTraits;
 
 	asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() );
 
 	// Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
-	asASSERT( !(!objType && isFinal) );
-	asASSERT( !(!objType && isOverride) );
+	asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_FINAL)) );
+	asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_OVERRIDE)) );
 
 	// The internal ref count was already set by the constructor
 	scriptFunctions.PushLast(func);
@@ -1304,7 +1279,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
 	return 0;
 }
 
-// internal 
+// internal
 int asCModule::AddScriptFunction(asCScriptFunction *func)
 {
 	scriptFunctions.PushLast(func);
@@ -1314,9 +1289,9 @@ int asCModule::AddScriptFunction(asCScriptFunction *func)
 	// If the function that is being added is an already compiled shared function
 	// then it is necessary to look for anonymous functions that may be declared
 	// within it and add those as well
-	if( func->isShared && func->funcType == asFUNC_SCRIPT )
+	if( func->IsShared() && func->funcType == asFUNC_SCRIPT )
 	{
-		// Loop through the byte code and check all the 
+		// Loop through the byte code and check all the
 		// asBC_FuncPtr instructions for anonymous functions
 		asDWORD *bc = func->scriptData->byteCode.AddressOf();
 		asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength();
@@ -1410,7 +1385,7 @@ int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
 		return asINVALID_ARG;
 
 	asCScriptFunction *src = engine->GetScriptFunction(func->GetId());
-	if( src == 0 ) 
+	if( src == 0 )
 		return asNO_FUNCTION;
 
 	// Verify return type
@@ -1624,7 +1599,7 @@ int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
 {
 	if( in == 0 ) return asINVALID_ARG;
 
-	// Don't allow the module to be rebuilt if there are still 
+	// Don't allow the module to be rebuilt if there are still
 	// external references that will need the previous code
 	if( HasExternalReferences(false) )
 	{
@@ -1701,12 +1676,12 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l
 	// Initialize the variable
 	if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
 	{
-		// Clear the memory 
+		// Clear the memory
 		asCGlobalProperty *prop = scriptGlobals.GetLast();
 		if( prop )
 		{
 			memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
-	
+
 			if( prop->GetInitFunc() )
 			{
 				// Call the init function for the global variable
@@ -1714,11 +1689,11 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l
 				r = engine->CreateContext(&ctx, true);
 				if( r < 0 )
 					return r;
-	
+
 				r = ctx->Prepare(prop->GetInitFunc());
 				if( r >= 0 )
 					r = ctx->Execute();
-	
+
 				ctx->Release();
 			}
 		}
@@ -1731,7 +1706,7 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l
 // interface
 int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
 {
-	// Make sure the outFunc is null if the function fails, so the 
+	// Make sure the outFunc is null if the function fails, so the
 	// application doesn't attempt to release a non-existent function
 	if( outFunc )
 		*outFunc = 0;
@@ -1744,7 +1719,7 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li
 	return asNOT_SUPPORTED;
 #else
 	// Validate arguments
-	if( code == 0 || 
+	if( code == 0 ||
 		(compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
 		return asINVALID_ARG;
 

+ 11 - 23
source/as_module.h

@@ -2,23 +2,23 @@
    AngelCode Scripting Library
    Copyright (c) 2003-2017 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -82,7 +82,7 @@ struct sObjectTypePair
 // TODO: Need a separate interface for compiling scripts. The asIScriptCompiler
 //       will have a target module, and will allow the compilation of an entire
 //       script or just individual functions within the scope of the module
-// 
+//
 //       With this separation it will be possible to compile the library without
 //       the compiler, thus giving a much smaller binary executable.
 
@@ -133,11 +133,6 @@ public:
 	// Type identification
 	virtual asUINT         GetObjectTypeCount() const;
 	virtual asITypeInfo   *GetObjectTypeByIndex(asUINT index) const;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual asITypeInfo   *GetObjectTypeByName(const char *name) const;
-	virtual asITypeInfo   *GetObjectTypeByDecl(const char *decl) const;
-#endif
 	virtual int            GetTypeIdByDecl(const char *decl) const;
 	virtual asITypeInfo   *GetTypeInfoByName(const char *name) const;
 	virtual asITypeInfo   *GetTypeInfoByDecl(const char *decl) const;
@@ -145,11 +140,6 @@ public:
 	// Enums
 	virtual asUINT       GetEnumCount() const;
 	virtual asITypeInfo *GetEnumByIndex(asUINT index) const;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual int          GetEnumValueCount(int enumTypeId) const;
-	virtual const char * GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const;
-#endif
 
 	// Typedefs
 	virtual asUINT       GetTypedefCount() const;
@@ -196,7 +186,7 @@ public:
 	void JITCompile();
 
 #ifndef AS_NO_COMPILER
-	int  AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType = 0, bool isConstMethod = false, bool isGlobalFunction = false, bool isPrivate = false, bool isProtected = false, bool isFinal = false, bool isOverride = false, bool isShared = false, asSNameSpace *ns = 0);
+	int  AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType = 0, bool isGlobalFunction = false, asSFunctionTraits funcTraits = asSFunctionTraits(), asSNameSpace *ns = 0);
 	int  AddScriptFunction(asCScriptFunction *func);
 	int  AddImportedFunction(int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, asSNameSpace *ns, const asCString &moduleName);
 	int  AddFuncDef(const asCString &name, asSNameSpace *ns, asCObjectType *parent);
@@ -220,7 +210,7 @@ public:
 	// This array holds all functions, class members, factories, etc that were compiled with the module.
 	// These references hold an internal reference to the function object.
 	asCArray<asCScriptFunction *>     scriptFunctions; // increases ref count
-	// This array holds global functions declared in the module. These references are not counted, 
+	// This array holds global functions declared in the module. These references are not counted,
 	// as the same pointer is always present in the scriptFunctions array too.
 	asCSymbolTable<asCScriptFunction> globalFunctions; // doesn't increase ref count
 	// This array holds imported functions in the module.
@@ -241,12 +231,10 @@ public:
 	// This array holds the funcdefs declared in the module
 	asCArray<asCFuncdefType*>      funcDefs; // increases ref count
 
-#ifndef AS_NO_COMPILER
 	// This array holds types that have been explicitly declared with 'external'
 	asCArray<asCTypeInfo*>       externalTypes; // doesn't increase ref count
 	// This array holds functions that have been explicitly declared with 'external'
 	asCArray<asCScriptFunction*> externalFunctions; // doesn't increase ref count
-#endif
 };
 
 END_AS_NAMESPACE

+ 5 - 1
source/as_objecttype.cpp

@@ -337,7 +337,7 @@ asUINT asCObjectType::GetPropertyCount() const
 }
 
 // interface
-int asCObjectType::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask) const
+int asCObjectType::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect) const
 {
 	if( index >= properties.GetLength() )
 		return asINVALID_ARG;
@@ -357,6 +357,10 @@ int asCObjectType::GetProperty(asUINT index, const char **out_name, int *out_typ
 		*out_isReference = prop->type.IsReference();
 	if( out_accessMask )
 		*out_accessMask = prop->accessMask;
+	if (out_compositeOffset)
+		*out_compositeOffset = prop->compositeOffset;
+	if (out_isCompositeIndirect)
+		*out_isCompositeIndirect = prop->isCompositeIndirect;
 
 	return 0;
 }

+ 2 - 2
source/as_objecttype.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -117,7 +117,7 @@ public:
 	asIScriptFunction *GetMethodByName(const char *name, bool getVirtual) const;
 	asIScriptFunction *GetMethodByDecl(const char *decl, bool getVirtual) const;
 	asUINT             GetPropertyCount() const;
-	int                GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask) const;
+	int                GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask, int *compositeOffset, bool *isCompositeIndirect) const;
 	const char        *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const;
 	asUINT             GetBehaviourCount() const;
 	asIScriptFunction *GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const;

Разлика између датотеке није приказан због своје велике величине
+ 237 - 270
source/as_parser.cpp


+ 11 - 10
source/as_parser.h

@@ -1,24 +1,24 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -66,7 +66,7 @@ public:
 	int ParseVarInit(asCScriptCode *script, asCScriptNode *init);
 	int ParseExpression(asCScriptCode *script);
 #endif
-	
+
 	asCScriptNode *GetScriptNode();
 
 protected:
@@ -96,6 +96,7 @@ protected:
 
 	bool IsRealType(int tokenType);
 	bool IsDataType(const sToken &token);
+	bool IsType(sToken &nextToken);
 	bool IdentifierIs(const sToken &t, const char *str);
 
 #ifndef AS_NO_COMPILER

+ 13 - 11
source/as_property.h

@@ -1,24 +1,24 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -53,12 +53,14 @@ struct asSNameSpace;
 class asCObjectProperty
 {
 public:
-	asCObjectProperty() {accessMask = 0xFFFFFFFF;}
-	asCObjectProperty(const asCObjectProperty &o) : name(o.name), type(o.type), byteOffset(o.byteOffset), accessMask(o.accessMask), isPrivate(o.isPrivate), isProtected(o.isProtected), isInherited(o.isInherited) {}
+	asCObjectProperty() : byteOffset(0), accessMask(0xFFFFFFFF), compositeOffset(0), isCompositeIndirect(false), isPrivate(false), isProtected(false), isInherited(false) {}
+	asCObjectProperty(const asCObjectProperty &o) : name(o.name), type(o.type), byteOffset(o.byteOffset), accessMask(o.accessMask), compositeOffset(o.compositeOffset), isCompositeIndirect(o.isCompositeIndirect), isPrivate(o.isPrivate), isProtected(o.isProtected), isInherited(o.isInherited) {}
 	asCString   name;
 	asCDataType type;
 	int         byteOffset;
 	asDWORD     accessMask;
+	int         compositeOffset;
+	bool        isCompositeIndirect;
 	bool        isPrivate;
 	bool        isProtected;
 	bool        isInherited;

Разлика између датотеке није приказан због своје велике величине
+ 336 - 226
source/as_restore.cpp


+ 16 - 12
source/as_restore.h

@@ -64,7 +64,7 @@ protected:
 
 	int                ReadInner();
 
-	void               ReadData(void *data, asUINT size);
+	int                ReadData(void *data, asUINT size);
 	void               ReadString(asCString *str);
 	asCScriptFunction *ReadFunction(bool &isNew, bool addToModule = true, bool addToEngine = true, bool addToGC = true, bool *isExternal = 0);
 	void               ReadFunctionSignature(asCScriptFunction *func, asCObjectType **parentClass = 0);
@@ -102,7 +102,7 @@ protected:
 	asCArray<asCTypeInfo*>       usedTypes;
 	asCArray<asCScriptFunction*> usedFunctions;
 	asCArray<void*>              usedGlobalProperties;
-	asCArray<int>                usedStringConstants;
+	asCArray<void*>              usedStringConstants;
 
 	asCArray<asCScriptFunction*>  savedFunctions;
 	asCArray<asCDataType>         savedDataTypes;
@@ -113,8 +113,8 @@ protected:
 
 	struct SObjProp
 	{
-		asCObjectType *objType;
-		int            offset;
+		asCObjectType     *objType;
+		asCObjectProperty *prop;
 	};
 	asCArray<SObjProp> usedObjectProperties;
 
@@ -165,8 +165,12 @@ protected:
 	asIBinaryStream *stream;
 	asCScriptEngine *engine;
 	bool             stripDebugInfo;
+	bool             error;
+	asUINT           bytesWritten;
+
+	int              Error(const char *msg);
 
-	void WriteData(const void *data, asUINT size);
+	int  WriteData(const void *data, asUINT size);
 
 	void WriteString(asCString *str);
 	void WriteFunction(asCScriptFunction *func);
@@ -184,8 +188,8 @@ protected:
 	int FindTypeIdIdx(int typeId);
 	int FindFunctionIndex(asCScriptFunction *func);
 	int FindGlobalPropPtrIndex(void *);
-	int FindStringConstantIndex(int id);
-	int FindObjectPropIndex(short offset, int typeId);
+	int FindStringConstantIndex(void *str);
+	int FindObjectPropIndex(short offset, int typeId, asDWORD *bc);
 
 	void CalculateAdjustmentByPos(asCScriptFunction *func);
 	int  AdjustStackPosition(int pos);
@@ -204,21 +208,21 @@ protected:
 	asCArray<asCTypeInfo*>       usedTypes;
 	asCArray<asCScriptFunction*> usedFunctions;
 	asCArray<void*>              usedGlobalProperties;
-	asCArray<int>                usedStringConstants;
-	asCMap<int, int>             stringIdToIndexMap;
+	asCArray<void*>              usedStringConstants;
+	asCMap<void*, int>           stringToIndexMap;
 
 	asCArray<asCScriptFunction*>  savedFunctions;
 	asCArray<asCDataType>         savedDataTypes;
 	asCArray<asCString>           savedStrings;
-	asCMap<asCStringPointer, int> stringToIdMap;
+	asCMap<asCString, int>        stringToIdMap;
 	asCArray<int>                 adjustStackByPos;
 	asCArray<int>                 adjustNegativeStackByPos;
 	asCArray<int>                 bytecodeNbrByPos;
 
 	struct SObjProp
 	{
-		asCObjectType *objType;
-		int            offset;
+		asCObjectType     *objType;
+		asCObjectProperty *prop;
 	};
 	asCArray<SObjProp>           usedObjectProperties;
 

Разлика између датотеке није приказан због своје велике величине
+ 253 - 217
source/as_scriptengine.cpp


+ 38 - 60
source/as_scriptengine.h

@@ -1,24 +1,24 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -28,7 +28,6 @@
    [email protected]
 */
 
-// Modified by Lasse Oorni for Urho3D
 
 //
 // as_scriptengine.h
@@ -101,21 +100,16 @@ public:
 
 	// Type registration
 	virtual int            RegisterObjectType(const char *obj, int byteSize, asDWORD flags);
-	virtual int            RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset);
-	virtual int            RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0);
-	virtual int            RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0);
+	virtual int            RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset = 0, bool isCompositeIndirect = false);
+	virtual int            RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false);
+	virtual int            RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false);
 	virtual int            RegisterInterface(const char *name);
 	virtual int            RegisterInterfaceMethod(const char *intf, const char *declaration);
 	virtual asUINT         GetObjectTypeCount() const;
 	virtual asITypeInfo   *GetObjectTypeByIndex(asUINT index) const;
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual asITypeInfo   *GetObjectTypeByName(const char *name) const;
-	virtual asITypeInfo   *GetObjectTypeByDecl(const char *decl) const;
-#endif
 
 	// String factory
-	virtual int RegisterStringFactory(const char *datatype, const asSFuncPtr &factoryFunc, asDWORD callConv, void *auxiliary = 0);
+	virtual int RegisterStringFactory(const char *datatype, asIStringFactory *factory);
 	virtual int GetStringFactoryReturnTypeId(asDWORD *flags) const;
 
 	// Default array type
@@ -127,10 +121,6 @@ public:
 	virtual int          RegisterEnumValue(const char *type, const char *name, int value);
 	virtual asUINT       GetEnumCount() const;
 	virtual asITypeInfo *GetEnumByIndex(asUINT index) const;
-	// Urho3D: removed deprecation for ScriptAPIDump
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual int          GetEnumValueCount(int enumTypeId) const;
-	virtual const char * GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const;
 
 	// Funcdefs
 	virtual int          RegisterFuncdef(const char *decl);
@@ -159,16 +149,8 @@ public:
 
 	// Script functions
 	virtual asIScriptFunction *GetFunctionById(int funcId) const;
-#ifdef AS_DEPRECATED
-	// deprecated since 2.31.0, 2016-01-01
-	virtual asIScriptFunction *GetFuncdefFromTypeId(int typeId) const;
-#endif
 
 	// Type identification
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual asITypeInfo   *GetObjectTypeById(int typeId) const;
-#endif
 	virtual int            GetTypeIdByDecl(const char *decl) const;
 	virtual const char    *GetTypeDeclaration(int typeId, bool includeNamespace = false) const;
 	virtual int            GetSizeOfPrimitiveType(int typeId) const;
@@ -186,10 +168,6 @@ public:
 	virtual void                   ReleaseScriptObject(void *obj, const asITypeInfo *type);
 	virtual void                   AddRefScriptObject(void *obj, const asITypeInfo *type);
 	virtual int                    RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo *toType, void **newPtr, bool useOnlyImplicitCast = false);
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.30.0, 2014-11-04
-	virtual bool                   IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const;
-#endif
 	virtual asILockableSharedBool *GetWeakRefFlagOfScriptObject(void *obj, const asITypeInfo *type) const;
 
 	// Context pooling
@@ -206,6 +184,9 @@ public:
 	virtual int  NotifyGarbageCollectorOfNewObject(void *obj, asITypeInfo *type);
 	virtual int  GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj = 0, asITypeInfo **type = 0);
 	virtual void GCEnumCallback(void *reference);
+	virtual void ForwardGCEnumReferences(void *ref, asITypeInfo *type);
+	virtual void ForwardGCReleaseReferences(void *ref, asITypeInfo *type);
+	virtual void SetCircularRefDetectedCallback(asCIRCULARREFFUNC_t callback, void *param = 0);
 
 	// User data
 	virtual void *SetUserData(void *data, asPWORD type);
@@ -214,13 +195,12 @@ public:
 	virtual void  SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback, asPWORD type);
 	virtual void  SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback, asPWORD type);
 	virtual void  SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback, asPWORD type);
-#ifdef AS_DEPRECATED
-	// Deprecated since 2.31.0, 2015-12-06
-	virtual void  SetObjectTypeUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type);
-#endif
 	virtual void  SetTypeInfoUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type);
 	virtual void  SetScriptObjectUserDataCleanupCallback(asCLEANSCRIPTOBJECTFUNC_t callback, asPWORD type);
 
+	// Exception handling
+	virtual int SetTranslateAppExceptionCallback(asSFuncPtr callback, void *param, int callConv);
+
 //===========================================================
 // internal methods
 //===========================================================
@@ -238,8 +218,8 @@ public:
 	friend class asCByteCode;
 	friend int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine *engine);
 
-	int RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0);
-	int RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0);
+	int RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false);
+	int RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false);
 
 	int VerifyVarTypeNotInFunction(asCScriptFunction *func);
 
@@ -325,11 +305,6 @@ public:
 
 	asCFuncdefType    *FindMatchingFuncdef(asCScriptFunction *func, asCModule *mod);
 
-	// String constants
-	// TODO: Must free unused string constants, thus the ref count for each must be tracked
-	int              AddConstantString(const char *str, size_t length);
-	const asCString &GetConstantString(int id);
-
 	// Global property management
 	asCGlobalProperty *AllocateGlobalProperty();
 	void RemoveGlobalProperty(asCGlobalProperty *prop);
@@ -361,17 +336,18 @@ public:
 	asCSymbolTable<asCScriptFunction> registeredGlobalFuncs;
 	asCArray<asCFuncdefType *>        registeredFuncDefs;      // doesn't increase ref count
 	asCArray<asCObjectType *>         registeredTemplateTypes; // doesn't increase ref count
-	asCScriptFunction                *stringFactory;
+	asIStringFactory                 *stringFactory;
+	asCDataType                       stringType;
 	bool configFailed;
 
 	// Stores all registered types
 	asCMap<asSNameSpaceNamePair, asCTypeInfo*> allRegisteredTypes; // increases ref count
 
-	// Dummy types used to name the subtypes in the template objects 
+	// Dummy types used to name the subtypes in the template objects
 	asCArray<asCTypeInfo *>        templateSubTypes;
 
 	// Store information about template types
-	// This list will contain all instances of templates, both registered specialized 
+	// This list will contain all instances of templates, both registered specialized
 	// types and those automacially instantiated from scripts
 	asCArray<asCObjectType *>      templateInstanceTypes; // increases ref count
 
@@ -402,7 +378,7 @@ public:
 	// This array holds all live script modules
 	asCArray<asCModule *>  scriptModules;
 	// Synchronized with engineRWLock
-	// This is a pointer to the last module that was requested. It is used for performance 
+	// This is a pointer to the last module that was requested. It is used for performance
 	// improvement, since it is common that the same module is accessed many times in a row
 	asCModule             *lastModule;
 	// Synchronized with engineRWLock
@@ -413,8 +389,8 @@ public:
 	// This array holds modules that have been discard (thus are no longer visible to the application)
 	// but cannot yet be deleted due to having external references to some of the entities in them
 	asCArray<asCModule *>  discardedModules;
-	// This flag is set to true during compilations of scripts (or loading pre-compiled scripts) 
-	// to delay the validation of template types until the subtypes have been fully declared 
+	// This flag is set to true during compilations of scripts (or loading pre-compiled scripts)
+	// to delay the validation of template types until the subtypes have been fully declared
 	bool                   deferValidationOfTemplateTypes;
 
 	// Tokenizer is instantiated once to share resources
@@ -464,16 +440,10 @@ public:
 	asIJITCompiler             *jitCompiler;
 
 	// Namespaces
-	// These are shared between all entities and are 
+	// These are shared between all entities and are
 	// only deleted once the engine is destroyed
 	asCArray<asSNameSpace*> nameSpaces;
 
-	// String constants
-	// These are shared between all scripts and are
-	// only deleted once the engine is destroyed
-	asCArray<asCString*>          stringConstants;
-	asCMap<asCStringPointer, int> stringToIdMap;
-
 	// Callbacks for context pooling
 	asREQUESTCONTEXTFUNC_t  requestCtxFunc;
 	asRETURNCONTEXTFUNC_t   returnCtxFunc;
@@ -530,12 +500,20 @@ public:
 		bool   allowUnicodeIdentifiers;
 		int    heredocTrimMode;
 		asUINT maxNestedCalls;
+		asUINT genericCallMode;
 	} ep;
 
+	// Callbacks
+#ifndef AS_NO_EXCEPTIONS
+	bool                       translateExceptionCallback;
+	asSSystemFunctionInterface translateExceptionCallbackFunc;
+	void *                     translateExceptionCallbackObj;
+#endif
+
 	// This flag is to allow a quicker shutdown when releasing the engine
 	bool shuttingDown;
 
-	// This flag is set when the engine's destructor is called, this is to 
+	// This flag is set when the engine's destructor is called, this is to
 	// avoid recursive calls if an object happens to increment/decrement
 	// the ref counter during shutdown
 	bool inDestructor;

+ 51 - 36
source/as_scriptfunction.cpp

@@ -359,11 +359,6 @@ asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, as
 	module                 = mod;
 	objectType             = 0;
 	name                   = "";
-	isReadOnly             = false;
-	isPrivate              = false;
-	isProtected            = false;
-	isFinal                = false;
-	isOverride             = false;
 	sysFuncIntf            = 0;
 	signatureId            = 0;
 	dontCleanUpOnException = false;
@@ -372,7 +367,6 @@ asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, as
 	userData               = 0;
 	id                     = 0;
 	accessMask             = 0xFFFFFFFF;
-	isShared               = false;
 	nameSpace              = engine->nameSpaces[0];
 	objForDelegate         = 0;
 	funcForDelegate        = 0;
@@ -636,19 +630,19 @@ const char *asCScriptFunction::GetNamespace() const
 // interface
 bool asCScriptFunction::IsReadOnly() const
 {
-	return isReadOnly;
+	return traits.GetTrait(asTRAIT_CONST);
 }
 
 // interface
 bool asCScriptFunction::IsPrivate() const
 {
-	return isPrivate;
+	return traits.GetTrait(asTRAIT_PRIVATE);
 }
 
 // interface
 bool asCScriptFunction::IsProtected() const
 {
-	return isProtected;
+	return traits.GetTrait(asTRAIT_PROTECTED);
 }
 
 // internal
@@ -789,7 +783,7 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool incl
 
 	str += ")";
 
-	if( isReadOnly )
+	if( IsReadOnly() )
 		str += " const";
 
 	// Add the declaration of the list pattern
@@ -1038,7 +1032,7 @@ bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
 // internal
 bool asCScriptFunction::IsSignatureExceptNameEqual(const asCScriptFunction *func) const
 {
-	return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly);
+	return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->IsReadOnly());
 }
 
 // internal
@@ -1052,19 +1046,19 @@ bool asCScriptFunction::IsSignatureExceptNameEqual(const asCDataType &retType, c
 // internal
 bool asCScriptFunction::IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const
 {
-	return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, isReadOnly);
+	return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, IsReadOnly());
 }
 
 // internal
 bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *func) const
 {
-	return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly);
+	return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->IsReadOnly());
 }
 
 // internal
 bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
 {
-	if( this->isReadOnly        != readOnly       ) return false;
+	if( this->IsReadOnly()      != readOnly       ) return false;
 	if( (this->objectType != 0) != (objType != 0) ) return false;
 	if( this->inOutFlags        != paramInOut     ) return false;
 	if( this->parameterTypes    != paramTypes     ) return false;
@@ -1158,7 +1152,31 @@ void asCScriptFunction::AddReferences()
 					void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
 					if( !gvarPtr ) break;
 					asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
-					if( !prop ) break;
+
+					if (!prop)
+					{
+						// The pointer is a string constant. In order to make sure the correct resource
+						// management is maintained we request a new string constant here, so the compiler
+						// or bytecode loader can release its copy afterwards.
+						asCString str;
+						asUINT length;
+						int r = engine->stringFactory->GetRawStringData(gvarPtr, 0, &length);
+						if (r >= 0)
+						{
+							str.SetLength(length);
+							engine->stringFactory->GetRawStringData(gvarPtr, str.AddressOf(), &length);
+
+							// Get a new pointer (depending on the string factory implementation it may actually be the same)
+							gvarPtr = const_cast<void*>(engine->stringFactory->GetStringConstant(str.AddressOf(), length));
+							asBC_PTRARG(&bc[n]) = (asPWORD)gvarPtr;
+						}
+						
+						// If we get an error from the string factory there is not
+						// anything we can do about it, except report a message.
+						// TODO: NEWSTRING: Write a message and then exit gracefully
+						asASSERT(r >= 0);
+						break;
+					}
 
 					// Only addref the properties once
 					if( !ptrs.Exists(gvarPtr) )
@@ -1299,7 +1317,21 @@ void asCScriptFunction::ReleaseReferences()
 					void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
 					if( !gvarPtr ) break;
 					asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
-					if( !prop ) break;
+
+					if (!prop)
+					{
+						// The pointer is a string constant, so it needs to be released by the string factory
+						int r = engine->stringFactory->ReleaseStringConstant(gvarPtr);
+						UNUSED_VAR(r);
+
+						// If we get an error from the string factory there is not
+						// anything we can do about it, except report a message.
+						// TODO: Write a message showing that the string couldn't be 
+						//       released. Include the first 10 characters and the length
+						//       to make it easier to identify which string it was
+						asASSERT(r >= 0);
+						break;
+					}
 
 					// Only release the properties once
 					if( !ptrs.Exists(gvarPtr) )
@@ -1433,23 +1465,6 @@ int asCScriptFunction::GetParam(asUINT index, int *out_typeId, asDWORD *out_flag
 	return asSUCCESS;
 }
 
-#ifdef AS_DEPRECATED
-// Deprecated since 2014-04-06, 2.29.0
-int asCScriptFunction::GetParamTypeId(asUINT index, asDWORD *flags) const
-{
-	if( index >= parameterTypes.GetLength() )
-		return asINVALID_ARG;
-
-	if( flags )
-	{
-		*flags = inOutFlags[index];
-		*flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0;
-	}
-
-	return engine->GetTypeIdFromDataType(parameterTypes[index]);
-}
-#endif
-
 // interface
 asIScriptEngine *asCScriptFunction::GetEngine() const
 {
@@ -1682,19 +1697,19 @@ bool asCScriptFunction::IsShared() const
 	if (funcType == asFUNC_FUNCDEF && module == 0) return true;
 
 	// Functions that have been specifically marked as shared are shared
-	return isShared;
+	return traits.GetTrait(asTRAIT_SHARED);
 }
 
 // internal
 bool asCScriptFunction::IsFinal() const
 {
-	return isFinal;
+	return traits.GetTrait(asTRAIT_FINAL);
 }
 
 // internal
 bool asCScriptFunction::IsOverride() const
 {
-	return isOverride;
+	return traits.GetTrait(asTRAIT_OVERRIDE);
 }
 
 END_AS_NAMESPACE

+ 45 - 25
source/as_scriptfunction.h

@@ -1,24 +1,24 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -97,6 +97,28 @@ enum asEObjVarInfoOption
 	asBLOCK_END
 };
 
+enum asEFuncTrait
+{
+	asTRAIT_CONSTRUCTOR = 1,
+	asTRAIT_DESTRUCTOR  = 2,
+	asTRAIT_CONST       = 4,
+	asTRAIT_PRIVATE     = 8,
+	asTRAIT_PROTECTED   = 16,
+	asTRAIT_FINAL       = 32,
+	asTRAIT_OVERRIDE    = 64,
+	asTRAIT_SHARED      = 128,
+	asTRAIT_EXTERNAL    = 256
+};
+
+struct asSFunctionTraits
+{
+	asSFunctionTraits() : traits(0) {}
+	void SetTrait(asEFuncTrait trait, bool set) { if (set) traits |= trait; else traits &= ~trait; }
+	bool GetTrait(asEFuncTrait trait) const { return (traits & trait) ? true : false; }
+protected:
+	asDWORD traits;
+};
+
 struct asSObjectVariableInfo
 {
 	asUINT              programPos;
@@ -106,8 +128,8 @@ struct asSObjectVariableInfo
 
 struct asSSystemFunctionInterface;
 
-// TODO: Might be interesting to allow enumeration of accessed global variables, and 
-//       also functions/methods that are being called. This could be used to build a 
+// TODO: Might be interesting to allow enumeration of accessed global variables, and
+//       also functions/methods that are being called. This could be used to build a
 //       code database with call graphs, etc.
 
 void RegisterScriptFunction(asCScriptEngine *engine);
@@ -146,13 +168,9 @@ public:
 	bool                 IsShared() const;
 	asUINT               GetParamCount() const;
 	int                  GetParam(asUINT index, int *typeId, asDWORD *flags = 0, const char **name = 0, const char **defaultArg = 0) const;
-#ifdef AS_DEPRECATED
-	// Deprecated, since 2.29.0, 2014-04-06
-	int                  GetParamTypeId(asUINT index, asDWORD *flags = 0) const;
-#endif
 	int                  GetReturnTypeId(asDWORD *flags = 0) const;
 
-	// Type id for function pointers 
+	// Type id for function pointers
 	int                  GetTypeId() const;
 	bool                 IsCompatibleWithTypeId(int typeId) const;
 
@@ -178,10 +196,17 @@ public:
 	//-----------------------------------
 	// Internal methods
 
+	void SetShared(bool set) {traits.SetTrait(asTRAIT_SHARED, set);}
+	void SetReadOnly(bool set) { traits.SetTrait(asTRAIT_CONST, set); }
+	void SetFinal(bool set) { traits.SetTrait(asTRAIT_FINAL, set); }
+	void SetOverride(bool set) { traits.SetTrait(asTRAIT_OVERRIDE, set); }
+	void SetProtected(bool set) { traits.SetTrait(asTRAIT_PROTECTED, set); }
+	void SetPrivate(bool set) { traits.SetTrait(asTRAIT_PRIVATE, set); }
+
 	asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType funcType);
 	~asCScriptFunction();
 
-	// Keep an internal reference counter to separate references coming from 
+	// Keep an internal reference counter to separate references coming from
 	// application or script objects and references coming from the script code
 	int AddRefInternal();
 	int ReleaseInternal();
@@ -257,11 +282,7 @@ public:
 	asCArray<asCString>          parameterNames;
 	asCArray<asETypeModifiers>   inOutFlags;
 	asCArray<asCString *>        defaultArgs;
-	bool                         isReadOnly;
-	bool                         isPrivate;
-	bool                         isProtected;
-	bool                         isFinal;
-	bool                         isOverride;
+	asSFunctionTraits            traits;
 	asCObjectType               *objectType;
 	int                          signatureId;
 
@@ -269,10 +290,9 @@ public:
 
 	asEFuncType                  funcType;
 	asDWORD                      accessMask;
-	bool                         isShared;
 
-	// Namespace will be null for funcdefs that are declared as child funcdefs 
-	// of a class. In this case the namespace shall be taken from the parentClass 
+	// Namespace will be null for funcdefs that are declared as child funcdefs
+	// of a class. In this case the namespace shall be taken from the parentClass
 	// in the funcdefType
 	asSNameSpace                *nameSpace;
 

+ 120 - 15
source/as_scriptobject.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -121,6 +121,93 @@ asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngi
 	return ptr;
 }
 
+// This helper function will call the copy factory, that is a script function
+// TODO: Clean up: This function is almost identical to ScriptObjectFactory. Should make better use of the identical code.
+asIScriptObject *ScriptObjectCopyFactory(const asCObjectType *objType, void *origObj, asCScriptEngine *engine)
+{
+	asIScriptContext *ctx = 0;
+	int r = 0;
+	bool isNested = false;
+
+	// Use nested call in the context if there is an active context
+	ctx = asGetActiveContext();
+	if (ctx)
+	{
+		// It may not always be possible to reuse the current context, 
+		// in which case we'll have to create a new one any way.
+		if (ctx->GetEngine() == objType->GetEngine() && ctx->PushState() == asSUCCESS)
+			isNested = true;
+		else
+			ctx = 0;
+	}
+
+	if (ctx == 0)
+	{
+		// Request a context from the engine
+		ctx = engine->RequestContext();
+		if (ctx == 0)
+		{
+			// TODO: How to best report this failure?
+			return 0;
+		}
+	}
+
+	r = ctx->Prepare(engine->scriptFunctions[objType->beh.copyfactory]);
+	if (r < 0)
+	{
+		if (isNested)
+			ctx->PopState();
+		else
+			engine->ReturnContext(ctx);
+		return 0;
+	}
+
+	ctx->SetArgAddress(0, origObj);
+
+	for (;;)
+	{
+		r = ctx->Execute();
+
+		// We can't allow this execution to be suspended 
+		// so resume the execution immediately
+		if (r != asEXECUTION_SUSPENDED)
+			break;
+	}
+
+	if (r != asEXECUTION_FINISHED)
+	{
+		if (isNested)
+		{
+			ctx->PopState();
+
+			// If the execution was aborted or an exception occurred,
+			// then we should forward that to the outer execution.
+			if (r == asEXECUTION_EXCEPTION)
+			{
+				// TODO: How to improve this exception
+				ctx->SetException(TXT_EXCEPTION_IN_NESTED_CALL);
+			}
+			else if (r == asEXECUTION_ABORTED)
+				ctx->Abort();
+		}
+		else
+			engine->ReturnContext(ctx);
+		return 0;
+	}
+
+	asIScriptObject *ptr = (asIScriptObject*)ctx->GetReturnAddress();
+
+	// Increase the reference, because the context will release its pointer
+	ptr->AddRef();
+
+	if (isNested)
+		ctx->PopState();
+	else
+		engine->ReturnContext(ctx);
+
+	return ptr;
+}
+
 #ifdef AS_MAX_PORTABILITY
 
 static void ScriptObject_AddRef_Generic(asIScriptGeneric *gen)
@@ -726,14 +813,19 @@ void asCScriptObject::EnumReferences(asIScriptEngine *engine)
 	{
 		asCObjectProperty *prop = objType->properties[n];
 		void *ptr = 0;
-		if( prop->type.IsObject() )
+		if (prop->type.IsObject())
 		{
-			// TODO: gc: The members of the value type needs to be enumerated
-			//           too, since the value type may be holding a reference.
-			if( prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF) )
+			if (prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF))
 				ptr = *(void**)(((char*)this) + prop->byteOffset);
 			else
 				ptr = (void*)(((char*)this) + prop->byteOffset);
+
+			// The members of the value type needs to be enumerated
+			// too, since the value type may be holding a reference.
+			if ((prop->type.GetTypeInfo()->flags & asOBJ_VALUE) && (prop->type.GetTypeInfo()->flags & asOBJ_GC))
+			{
+				reinterpret_cast<asCScriptEngine*>(engine)->CallObjectMethod(ptr, engine, CastToObjectType(prop->type.GetTypeInfo())->beh.gcEnumReferences);
+			}
 		}
 		else if (prop->type.IsFuncdef())
 			ptr = *(void**)(((char*)this) + prop->byteOffset);
@@ -749,18 +841,31 @@ void asCScriptObject::ReleaseAllHandles(asIScriptEngine *engine)
 	{
 		asCObjectProperty *prop = objType->properties[n];
 
-		// TODO: gc: The members of the members needs to be released
-		//           too, since they may be holding a reference. Even
-		//           if the member is a value type.
-		if( prop->type.IsObject() && prop->type.IsObjectHandle() )
+		if (prop->type.IsObject())
 		{
-			void **ptr = (void**)(((char*)this) + prop->byteOffset);
-			if( *ptr )
+			if (prop->type.IsObjectHandle())
 			{
-				asASSERT( (prop->type.GetTypeInfo()->flags & asOBJ_NOCOUNT) || prop->type.GetBehaviour()->release );
-				if( prop->type.GetBehaviour()->release )
-					((asCScriptEngine*)engine)->CallObjectMethod(*ptr, prop->type.GetBehaviour()->release);
-				*ptr = 0;
+				void **ptr = (void**)(((char*)this) + prop->byteOffset);
+				if (*ptr)
+				{
+					asASSERT((prop->type.GetTypeInfo()->flags & asOBJ_NOCOUNT) || prop->type.GetBehaviour()->release);
+					if (prop->type.GetBehaviour()->release)
+						((asCScriptEngine*)engine)->CallObjectMethod(*ptr, prop->type.GetBehaviour()->release);
+					*ptr = 0;
+				}
+			}
+			else if ((prop->type.GetTypeInfo()->flags & asOBJ_VALUE) && (prop->type.GetTypeInfo()->flags & asOBJ_GC))
+			{
+				// The members of the members needs to be released
+				// too, since they may be holding a reference. Even
+				// if the member is a value type.
+				void *ptr = 0;
+				if (prop->type.IsReference())
+					ptr = *(void**)(((char*)this) + prop->byteOffset);
+				else
+					ptr = (void*)(((char*)this) + prop->byteOffset);
+
+				reinterpret_cast<asCScriptEngine*>(engine)->CallObjectMethod(ptr, engine, CastToObjectType(prop->type.GetTypeInfo())->beh.gcReleaseAllReferences);
 			}
 		}
 		else if (prop->type.IsFuncdef())

+ 13 - 12
source/as_scriptobject.h

@@ -1,24 +1,24 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -60,14 +60,14 @@ public:
 
 	bool Get() const;
 	void Set(bool);
-	
+
 	void Lock() const;
 	void Unlock() const;
 
 protected:
 	mutable asCAtomic refCount;
 	bool      value;
-	DECLARECRITICALSECTION(mutable lock);
+	DECLARECRITICALSECTION(mutable lock)
 };
 
 class asCScriptObject : public asIScriptObject
@@ -137,7 +137,7 @@ protected:
 	bool              isDestructCalled;
 
 	// Most script classes instances won't have neither the weakRefFlags nor
-	// userData so we only allocate this if requested. Even when used it is 
+	// userData so we only allocate this if requested. Even when used it is
 	// not something that will be accessed all the time so having the extra
 	// indirection will not affect the performance significantly.
 	struct SExtra
@@ -157,6 +157,7 @@ void ScriptObject_ConstructUnitialized(asCObjectType *objType, asCScriptObject *
 void RegisterScriptObject(asCScriptEngine *engine);
 
 asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngine *engine);
+asIScriptObject *ScriptObjectCopyFactory(const asCObjectType *objType, void *origObj, asCScriptEngine *engine);
 
 END_AS_NAMESPACE
 

+ 10 - 6
source/as_string.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2015 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -283,20 +283,24 @@ size_t asCString::Format(const char *format, ...)
 	va_list args;
 	va_start(args, format);
 
-	char tmp[256];
-	int r = asVSNPRINTF(tmp, 255, format, args);
+	const size_t startSize = 1024;
+	char tmp[startSize];
+	int r = asVSNPRINTF(tmp, startSize-1, format, args);
 
-	if( r > 0 )
+	if( r > 0 && r < int(startSize) )
 	{
 		Assign(tmp, r);
 	}
 	else
 	{
-		size_t n = 512;
+		// TODO: For some reason this doesn't work properly on Linux. Perhaps the
+		//       problem is related to vsnprintf not keeping the state of va_arg.
+		//       Perhaps I need to rewrite this in some way to keep the state
+		size_t n = startSize*2;
 		asCString str; // Use temporary string in case the current buffer is a parameter
 		str.Allocate(n, false);
 
-		while( (r = asVSNPRINTF(str.AddressOf(), n, format, args)) < 0 )
+		while( (r = asVSNPRINTF(str.AddressOf(), n, format, args)) < 0 || r >= int(n) )
 		{
 			n *= 2;
 			str.Allocate(n, false);

+ 55 - 12
source/as_texts.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2018 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -62,7 +62,8 @@
 #define TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES   "Can't inherit from multiple classes"
 #define TXT_CANNOT_INHERIT_FROM_SELF               "Can't inherit from itself, or another class that inherits from this class"
 #define TXT_CANNOT_PASS_CLASS_METHOD_AS_ARG        "Can't pass class method as arg directly. Use a delegate object instead"
-#define TXT_CANNOT_RESOLVE_AUTO                     "Unable to resolve auto type"
+#define TXT_CANNOT_RESOLVE_AUTO                    "Unable to resolve auto type"
+#define TXT_CANNOT_ACCESS_NON_STATIC_MEMBER_s      "Cannot access non-static member '%s' like this"
 #define TXT_CANNOT_RETURN_REF_TO_LOCAL             "Can't return reference to local value."
 #define TXT_CANT_CONSTRUCT_s_USE_REF_CAST          "Can't construct handle '%s'. Use ref cast instead"
 #define TXT_CANT_IMPLICITLY_CONVERT_s_TO_s         "Can't implicitly convert from '%s' to '%s'."
@@ -73,6 +74,8 @@
 #define TXT_COMPOUND_ASGN_ON_VALUE_TYPE            "Compound assignments with property accessors on value types are not supported"
 #define TXT_COMPOUND_ASGN_WITH_IDX_PROP            "Compound assignments with indexed property accessors are not supported"
 #define TXT_COMPOUND_ASGN_REQUIRE_GET_SET          "Compound assignments with property accessors require both get and set accessors"
+#define TXT_PROP_ACCESS_s_DOES_NOT_EXPECT_INDEX    "Implemented property accessor '%s' does not expect index argument"
+#define TXT_PROP_ACCESS_s_EXPECTS_INDEX            "Implemented property accessor '%s' expects index argument"
 
 #define TXT_DATA_TYPE_CANT_BE_s                     "Data type can't be '%s'"
 #define TXT_DECL_IN_SWITCH                          "Variables cannot be declared in switch cases, except inside statement blocks"
@@ -82,7 +85,7 @@
 #define TXT_DUPLICATE_NAMED_ARG                     "Duplicate named argument"
 #define TXT_DERIVED_METHOD_MUST_HAVE_SAME_RETTYPE_s "The method in the derived class must have the same return type as in the base class: '%s'"
 #define TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM            "The destructor must not have any parameters"
-#define TXT_DESTRUCTOR_s_s_NAME_ERROR              "The name of the destructor '%s::~%s' must be the same as the class"
+#define TXT_DESTRUCTOR_s_s_NAME_ERROR               "The name of the destructor '%s::~%s' must be the same as the class"
 #define TXT_DISALLOW_ASSIGN_ON_REF_TYPE             "Value assignment on reference types is not allowed. Did you mean to do a handle assignment?"
 #define TXT_DISALLOW_COMPOUND_ASSIGN_ON_REF_TYPE    "Compound assignment on reference types is not allowed"
 #define TXT_DUPLICATE_SWITCH_CASE                   "Duplicate switch case"
@@ -105,6 +108,7 @@
 #define TXT_EXPECTED_STRING                   "Expected string"
 #define TXT_EXPR_DOESNT_EVAL_TO_FUNC          "Expression doesn't evaluate to a function"
 #define TXT_EXPR_MUST_BE_BOOL                 "Expression must be of boolean type"
+#define TXT_EXPR_s_IS_DATA_TYPE               "Expression '%s' is a data type"
 #define TXT_EXTERNAL_SHARED_s_NOT_FOUND       "External shared entity '%s' not found"
 #define TXT_EXTERNAL_SHARED_s_CANNOT_REDEF    "External shared entity '%s' cannot redefine the original entity"
 
@@ -123,11 +127,11 @@
 #define TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED      "Handle to handle is not allowed"
 #define TXT_s_HIDES_VAR_IN_OUTER_SCOPE           "Variable '%s' hides another variable of same name in outer scope"
 
-#define TXT_IDENTIFIER_s_NOT_DATA_TYPE             "Identifier '%s' is not a data type"
+#define TXT_IDENTIFIER_s_NOT_DATA_TYPE              "Identifier '%s' is not a data type"
 #define TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS "Identifier '%s' is not a data type in global namespace"
-#define TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s     "Identifier '%s' is not a data type in namespace '%s' or parent"
-#define TXT_IF_WITH_EMPTY_STATEMENT                "If with empty statement"
-#define TXT_ILLEGAL_MEMBER_TYPE                    "Illegal member type"
+#define TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s      "Identifier '%s' is not a data type in namespace '%s' or parent"
+#define TXT_IF_WITH_EMPTY_STATEMENT                 "If with empty statement"
+#define TXT_ILLEGAL_MEMBER_TYPE                     "Illegal member type"
 // TODO: Should be TXT_ILLEGAL_OPERATION_ON_s
 #define TXT_ILLEGAL_OPERATION                      "Illegal operation on this datatype"
 #define TXT_ILLEGAL_OPERATION_ON_s                 "Illegal operation on '%s'"
@@ -154,11 +158,13 @@
 #define TXT_INVALID_UNICODE_FORMAT_EXPECTED_d      "Invalid unicode escape sequence, expected %d hex digits"
 #define TXT_INVALID_UNICODE_VALUE                  "Invalid unicode code point"
 #define TXT_INVALID_UNICODE_SEQUENCE_IN_SRC        "Invalid unicode sequence in source"
+#define TXT_INVALID_USE_OF_NAMED_ARGS              "Invalid use of named arguments"
 
 #define TXT_METHOD_CANNOT_OVERRIDE_s                "Method '%s' declared as final and cannot be overridden"
 #define TXT_METHOD_CANT_HAVE_NAME_OF_CLASS          "The method cannot be named with the class name"
 #define TXT_METHOD_s_DOES_NOT_OVERRIDE              "Method '%s' marked as override but does not replace any base class or interface method"
 #define TXT_METHOD_s_s_HAS_NO_RETURN_TYPE           "Method '%s::%s' is missing the return type, nor is it the same name as object to be a constructor"
+#define TXT_METHOD_s_NOT_PART_OF_OBJECT_s           "Method '%s' is not part of object '%s'"
 #define TXT_MISSING_IMPLEMENTATION_OF_s             "Missing implementation of '%s'"
 #define TXT_MISSING_DEFINITION_OF_s                 "Missing definition of '%s'"
 #define TXT_MIXIN_CANNOT_BE_DECLARED_AS_s           "Mixin class cannot be declared as '%s'"
@@ -196,9 +202,10 @@
 #define TXT_NO_MATCHING_SIGNATURES_TO_s            "No matching signatures to '%s'"
 #define TXT_NO_MATCHING_OP_FOUND_FOR_TYPE_s        "No matching operator that takes the type '%s' found"
 #define TXT_NO_MATCHING_OP_FOUND_FOR_TYPES_s_AND_s "No matching operator that takes the types '%s' and '%s' found"
+#define TXT_NO_MATCHING_SYMBOL_s                   "No matching symbol '%s'"
 #define TXT_NON_CONST_METHOD_ON_CONST_OBJ          "Non-const method call on read-only object reference"
 #define TXT_NONTERMINATED_STRING                   "Non-terminated string literal"
-#define TXT_NOT_A_FUNC_s_IS_VAR                    "Expression doesn't form a function call. '%s' is a variable of a non-function type"
+#define TXT_NOT_A_FUNC_s_IS_TYPE_s                 "Expression doesn't form a function call. '%s' evaluates to the non-function type '%s'"
 #define TXT_NOT_ALL_PATHS_RETURN                   "Not all paths return a value"
 #define TXT_NOT_ENOUGH_VALUES_FOR_LIST             "Not enough values to match pattern"
 #define TXT_s_NOT_DECLARED                         "'%s' is not declared"
@@ -297,7 +304,8 @@
 #define TXT_VALUE_TYPE_MUST_HAVE_SIZE                    "A value type must be registered with a non-zero size"
 #define TXT_TYPE_s_IS_MISSING_BEHAVIOURS                 "Type '%s' is missing behaviours"
 #define TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE                   "The behaviour is not compatible with the type"
-#define TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR              "A garbage collected type must have the addref, release, and all gc behaviours"
+#define TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR              "A garbage collected ref type must have the addref, release, and all gc behaviours"
+#define TXT_VALUE_GC_REQUIRE_GC_BEHAVIOUR                "A garbage collected value type must have the gc enum references behaviour"
 #define TXT_SCOPE_REQUIRE_REL_BEHAVIOUR                  "A scoped reference type must have the release behaviour"
 #define TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR                "A reference type must have the addref and release behaviours"
 #define TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR       "A non-pod value type must have at least one constructor and the destructor behaviours"
@@ -316,9 +324,9 @@
 #define TXT_TEMPLATE_LIST_FACTORY_EXPECTS_2_REF_PARAMS   "Template list factory expects two reference parameters. The last is the pointer to the initialization buffer"
 #define TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM             "List factory expects only one reference parameter. The pointer to the initialization buffer will be passed in this parameter"
 #define TXT_FAILED_READ_SUBTYPE_OF_TEMPLATE_s            "Failed to read subtype of template type '%s'"
-#define TXT_FAILED_IN_FUNC_s_d                           "Failed in call to function '%s' (Code: %d)"
-#define TXT_FAILED_IN_FUNC_s_WITH_s_d                    "Failed in call to function '%s' with '%s' (Code: %d)"
-#define TXT_FAILED_IN_FUNC_s_WITH_s_AND_s_d              "Failed in call to function '%s' with '%s' and '%s' (Code: %d)"
+#define TXT_FAILED_IN_FUNC_s_s_d                           "Failed in call to function '%s' (Code: %s, %d)"
+#define TXT_FAILED_IN_FUNC_s_WITH_s_s_d                    "Failed in call to function '%s' with '%s' (Code: %s, %d)"
+#define TXT_FAILED_IN_FUNC_s_WITH_s_AND_s_s_d              "Failed in call to function '%s' with '%s' and '%s' (Code: %s, %d)"
 #define TXT_GC_RECEIVED_NULL_PTR                         "AddScriptObjectToGC called with null pointer"
 #define TXT_EXCEPTION_IN_NESTED_CALL                     "An exception occurred in a nested call"
 #define TXT_TYPE_s_IS_STILL_USED_BY_FUNC_s               "Type '%s' is still used by function '%s'"
@@ -352,4 +360,39 @@
 #define TXT_MISMATCH_IN_VALUE_ASSIGN      "Mismatching types in value assignment"
 #define TXT_TOO_MANY_NESTED_CALLS         "Too many nested calls"
 
+// Error codes
+#define ERROR_NAME(x) #x
+static const char*const errorNames[] =
+{
+	ERROR_NAME(asSUCCESS),
+	ERROR_NAME(asERROR),
+	ERROR_NAME(asCONTEXT_ACTIVE),
+	ERROR_NAME(asCONTEXT_NOT_FINISHED),
+	ERROR_NAME(asCONTEXT_NOT_PREPARED),
+	ERROR_NAME(asINVALID_ARG),
+	ERROR_NAME(asNO_FUNCTION),
+	ERROR_NAME(asNOT_SUPPORTED),
+	ERROR_NAME(asINVALID_NAME),
+	ERROR_NAME(asNAME_TAKEN),
+	ERROR_NAME(asINVALID_DECLARATION),
+	ERROR_NAME(asINVALID_OBJECT),
+	ERROR_NAME(asINVALID_TYPE),
+	ERROR_NAME(asALREADY_REGISTERED),
+	ERROR_NAME(asMULTIPLE_FUNCTIONS),
+	ERROR_NAME(asNO_MODULE),
+	ERROR_NAME(asNO_GLOBAL_VAR),
+	ERROR_NAME(asINVALID_CONFIGURATION),
+	ERROR_NAME(asINVALID_INTERFACE),
+	ERROR_NAME(asCANT_BIND_ALL_FUNCTIONS),
+	ERROR_NAME(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED),
+	ERROR_NAME(asWRONG_CONFIG_GROUP),
+	ERROR_NAME(asCONFIG_GROUP_IS_IN_USE),
+	ERROR_NAME(asILLEGAL_BEHAVIOUR_FOR_TYPE),
+	ERROR_NAME(asWRONG_CALLING_CONV),
+	ERROR_NAME(asBUILD_IN_PROGRESS),
+	ERROR_NAME(asINIT_GLOBAL_VARS_FAILED),
+	ERROR_NAME(asOUT_OF_MEMORY),
+	ERROR_NAME(asMODULE_IS_IN_USE)
+};
+
 #endif

+ 2 - 2
source/as_thread.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2014 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -80,7 +80,7 @@ protected:
 #else
 	asDWORD tlsKey;
 #endif
-	DECLARECRITICALSECTION(criticalSection);
+	DECLARECRITICALSECTION(criticalSection)
 #else
 	asCThreadLocalData *tld;
 #endif

+ 10 - 10
source/as_tokendef.h

@@ -2,23 +2,23 @@
    AngelCode Scripting Library
    Copyright (c) 2003-2017 Andreas Jonsson
 
-   This software is provided 'as-is', without any express or implied 
-   warranty. In no event will the authors be held liable for any 
+   This software is provided 'as-is', without any express or implied
+   warranty. In no event will the authors be held liable for any
    damages arising from the use of this software.
 
-   Permission is granted to anyone to use this software for any 
-   purpose, including commercial applications, and to alter it and 
+   Permission is granted to anyone to use this software for any
+   purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
 
-   1. The origin of this software must not be misrepresented; you 
+   1. The origin of this software must not be misrepresented; you
       must not claim that you wrote the original software. If you use
-      this software in a product, an acknowledgment in the product 
+      this software in a product, an acknowledgment in the product
       documentation would be appreciated but is not required.
 
-   2. Altered source versions must be plainly marked as such, and 
+   2. Altered source versions must be plainly marked as such, and
       must not be misrepresented as being the original software.
 
-   3. This notice may not be removed or altered from any source 
+   3. This notice may not be removed or altered from any source
       distribution.
 
    The original version of this library can be located at:
@@ -244,7 +244,7 @@ sTokenWord const tokenWords[] =
 	asTokenDef("auto"      , ttAuto),
 	asTokenDef("bool"      , ttBool),
 	asTokenDef("break"     , ttBreak),
-	asTokenDef("case"      , ttCase), 
+	asTokenDef("case"      , ttCase),
 	asTokenDef("cast"      , ttCast),
 	asTokenDef("class"     , ttClass),
 	asTokenDef("const"     , ttConst),
@@ -269,7 +269,7 @@ sTokenWord const tokenWords[] =
 	asTokenDef("int"       , ttInt),
 	asTokenDef("int8"      , ttInt8),
 	asTokenDef("int16"     , ttInt16),
-	asTokenDef("int32"     , ttInt),  
+	asTokenDef("int32"     , ttInt),
 	asTokenDef("int64"     , ttInt64),
 	asTokenDef("interface" , ttInterface),
 	asTokenDef("is"        , ttIs),

+ 16 - 14
source/as_typeinfo.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2016 Andreas Jonsson
+   Copyright (c) 2003-2017 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -95,7 +95,7 @@ int asCTypeInfo::Release() const
 		// internal references then it is time to delete the object type
 		if (internalRefCount.get() == 0)
 		{
-			// If the engine is no longer set, then it has already been 
+			// If the engine is no longer set, then it has already been
 			// released and we must take care of the deletion ourselves
 			asDELETE(const_cast<asCTypeInfo*>(this), asCTypeInfo);
 		}
@@ -119,7 +119,7 @@ int asCTypeInfo::ReleaseInternal()
 		// external references then it is time to delete the object type
 		if (externalRefCount.get() == 0)
 		{
-			// If the engine is no longer set, then it has already been 
+			// If the engine is no longer set, then it has already been
 			// released and we must take care of the deletion ourselves
 			asDELETE(const_cast<asCTypeInfo*>(this), asCTypeInfo);
 		}
@@ -166,7 +166,7 @@ void *asCTypeInfo::SetUserData(void *data, asPWORD type)
 
 void *asCTypeInfo::GetUserData(asPWORD type) const
 {
-	// There may be multiple threads reading, but when  
+	// There may be multiple threads reading, but when
 	// setting the user data nobody must be reading.
 	ACQUIRESHARED(engine->engineRWLock);
 
@@ -251,7 +251,7 @@ asDWORD asCTypeInfo::GetAccessMask() const
 }
 
 // interface
-int asCTypeInfo::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask) const
+int asCTypeInfo::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect) const
 {
 	UNUSED_VAR(index);
 	if (out_name) *out_name = 0;
@@ -261,6 +261,8 @@ int asCTypeInfo::GetProperty(asUINT index, const char **out_name, int *out_typeI
 	if (out_offset) *out_offset = 0;
 	if (out_isReference) *out_isReference = false;
 	if (out_accessMask) *out_accessMask = 0;
+	if (out_compositeOffset) *out_compositeOffset = 0;
+	if (out_isCompositeIndirect) *out_isCompositeIndirect = false;
 	return -1;
 }
 
@@ -354,13 +356,13 @@ asCEnumType::~asCEnumType()
 
 // interface
 asUINT asCEnumType::GetEnumValueCount() const
-{ 
-	return enumValues.GetLength(); 
+{
+	return enumValues.GetLength();
 }
 
 // interface
 const char *asCEnumType::GetEnumValueByIndex(asUINT index, int *outValue) const
-{ 
+{
 	if (outValue)
 		*outValue = 0;
 
@@ -387,7 +389,7 @@ void asCTypedefType::DestroyInternal()
 	// Release the object types held by the alias
 	if (aliasForType.GetTypeInfo())
 			aliasForType.GetTypeInfo()->ReleaseInternal();
-	
+
 	aliasForType = asCDataType::CreatePrimitive(ttVoid, false);
 
 	CleanUserData();
@@ -402,8 +404,8 @@ void asCTypedefType::DestroyInternal()
 
 // interface
 int asCTypedefType::GetTypedefTypeId() const
-{ 
-	return engine->GetTypeIdFromDataType(aliasForType); 
+{
+	return engine->GetTypeIdFromDataType(aliasForType);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -414,7 +416,7 @@ asCFuncdefType::asCFuncdefType(asCScriptEngine *en, asCScriptFunction *func) : a
 	asASSERT(func->funcdefType == 0);
 
 	// A function pointer is special kind of reference type
-	flags       = asOBJ_REF | asOBJ_FUNCDEF | (func->isShared ? asOBJ_SHARED : 0);
+	flags       = asOBJ_REF | asOBJ_FUNCDEF | (func->IsShared() ? asOBJ_SHARED : 0);
 	name        = func->name;
 	nameSpace   = func->nameSpace;
 	module      = func->module;
@@ -458,8 +460,8 @@ void asCFuncdefType::DestroyInternal()
 
 // interface
 asIScriptFunction *asCFuncdefType::GetFuncdefSignature() const
-{ 
-	return funcdef; 
+{
+	return funcdef;
 }
 
 // interface

+ 1 - 1
source/as_typeinfo.h

@@ -105,7 +105,7 @@ public:
 
 	// Properties
 	asUINT      GetPropertyCount() const { return 0; }
-	int         GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask) const;
+	int         GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask, int *compositeOffset, bool *isCompositeIndirect) const;
 	const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const { UNUSED_VAR(index); UNUSED_VAR(includeNamespace); return 0; }
 
 	// Behaviours

Неке датотеке нису приказане због велике количине промена