Procházet zdrojové kódy

Merge branch 'master' into vulkan

rdb před 9 roky
rodič
revize
5b81285290
100 změnil soubory, kde provedl 4086 přidání a 2523 odebrání
  1. 43 0
      .gitignore
  2. 1 1
      .travis.yml
  3. 0 9
      contrib/.gitignore
  4. 0 2
      contrib/src/panda3dtoolsgui/.gitignore
  5. 0 9
      direct/.gitignore
  6. 0 1
      direct/src/configfiles/.gitignore
  7. 0 3
      direct/src/dcparser/.gitignore
  8. 0 106
      direct/src/directbase/ppython.cxx
  9. 10 1
      direct/src/directscripts/eggcacher.py
  10. 0 831
      direct/src/directscripts/packpanda.nsi
  11. 0 421
      direct/src/directscripts/packpanda.py
  12. 1 1
      direct/src/directtools/DirectCameraControl.py
  13. 3 3
      direct/src/directtools/DirectManipulation.py
  14. 1 1
      direct/src/directtools/DirectSession.py
  15. 1 5
      direct/src/distributed/DistributedObjectGlobalUD.py
  16. 3 3
      direct/src/distributed/cConnectionRepository.cxx
  17. 0 1
      direct/src/extensions_native/.gitignore
  18. 0 2
      direct/src/gui/.gitignore
  19. 3 3
      direct/src/gui/DirectScrolledList.py
  20. 0 8
      direct/src/p3d/.gitignore
  21. 11 1
      direct/src/p3d/Packager.py
  22. 7 0
      direct/src/p3d/panda3d.pdef
  23. 0 1
      direct/src/plugin/.gitignore
  24. 4 4
      direct/src/plugin/p3dInstance.cxx
  25. 11 0
      direct/src/plugin/p3dInstanceManager.cxx
  26. 8 8
      direct/src/plugin/p3dOsxSplashWindow.cxx
  27. 0 1
      direct/src/plugin_activex/.gitignore
  28. 0 1
      direct/src/plugin_npapi/.gitignore
  29. 0 2
      direct/src/plugin_standalone/.gitignore
  30. 12 3
      direct/src/showbase/BufferViewer.py
  31. 59 3
      direct/src/showbase/Loader.py
  32. 36 1
      direct/src/showbase/PythonUtil.py
  33. 0 4
      direct/src/showbase/ShowBase.py
  34. 0 1
      direct/src/showutil/.gitignore
  35. 4 1
      direct/src/task/Task.py
  36. 2 2
      direct/src/tkpanels/DirectSessionPanel.py
  37. 1 1
      direct/src/tkwidgets/MemoryExplorer.py
  38. 0 7
      dmodels/.gitignore
  39. 0 6
      dmodels/src/.gitignore
  40. 29 1
      doc/ReleaseNotes
  41. 0 7
      dtool/.gitignore
  42. 0 2
      dtool/src/cppparser/.gitignore
  43. 10 1
      dtool/src/cppparser/cppArrayType.cxx
  44. 1 0
      dtool/src/cppparser/cppArrayType.h
  45. 809 418
      dtool/src/cppparser/cppBison.cxx.prebuilt
  46. 310 253
      dtool/src/cppparser/cppBison.h.prebuilt
  47. 482 131
      dtool/src/cppparser/cppBison.yxx
  48. 4 0
      dtool/src/cppparser/cppBisonDefs.h
  49. 26 3
      dtool/src/cppparser/cppClassTemplateParameter.cxx
  50. 1 0
      dtool/src/cppparser/cppClassTemplateParameter.h
  51. 195 0
      dtool/src/cppparser/cppClosureType.cxx
  52. 65 0
      dtool/src/cppparser/cppClosureType.h
  53. 42 1
      dtool/src/cppparser/cppConstType.cxx
  54. 5 0
      dtool/src/cppparser/cppConstType.h
  55. 16 2
      dtool/src/cppparser/cppDeclaration.cxx
  56. 76 1
      dtool/src/cppparser/cppDeclaration.h
  57. 309 10
      dtool/src/cppparser/cppExpression.cxx
  58. 15 2
      dtool/src/cppparser/cppExpression.h
  59. 23 3
      dtool/src/cppparser/cppExtensionType.cxx
  60. 2 0
      dtool/src/cppparser/cppExtensionType.h
  61. 1 1
      dtool/src/cppparser/cppFile.h
  62. 67 14
      dtool/src/cppparser/cppFunctionType.cxx
  63. 6 1
      dtool/src/cppparser/cppFunctionType.h
  64. 8 5
      dtool/src/cppparser/cppInstance.cxx
  65. 7 0
      dtool/src/cppparser/cppInstance.h
  66. 7 7
      dtool/src/cppparser/cppInstanceIdentifier.cxx
  67. 4 0
      dtool/src/cppparser/cppInstanceIdentifier.h
  68. 14 1
      dtool/src/cppparser/cppParser.cxx
  69. 65 0
      dtool/src/cppparser/cppPointerType.cxx
  70. 2 0
      dtool/src/cppparser/cppPointerType.h
  71. 327 88
      dtool/src/cppparser/cppPreprocessor.cxx
  72. 8 0
      dtool/src/cppparser/cppPreprocessor.h
  73. 79 0
      dtool/src/cppparser/cppReferenceType.cxx
  74. 3 0
      dtool/src/cppparser/cppReferenceType.h
  75. 1 1
      dtool/src/cppparser/cppScope.cxx
  76. 3 2
      dtool/src/cppparser/cppScope.h
  77. 53 0
      dtool/src/cppparser/cppSimpleType.cxx
  78. 11 7
      dtool/src/cppparser/cppSimpleType.h
  79. 379 39
      dtool/src/cppparser/cppStructType.cxx
  80. 12 0
      dtool/src/cppparser/cppStructType.h
  81. 4 2
      dtool/src/cppparser/cppTemplateScope.cxx
  82. 8 0
      dtool/src/cppparser/cppToken.cxx
  83. 175 0
      dtool/src/cppparser/cppType.cxx
  84. 17 0
      dtool/src/cppparser/cppType.h
  85. 41 0
      dtool/src/cppparser/cppTypedefType.cxx
  86. 5 0
      dtool/src/cppparser/cppTypedefType.h
  87. 1 0
      dtool/src/cppparser/p3cppParser_composite1.cxx
  88. 9 2
      dtool/src/dtoolbase/deletedBufferChain.cxx
  89. 1 5
      dtool/src/dtoolbase/deletedBufferChain.h
  90. 7 2
      dtool/src/dtoolbase/dlmalloc_src.cxx
  91. 6 1
      dtool/src/dtoolbase/dtoolbase.h
  92. 50 3
      dtool/src/dtoolbase/dtoolbase_cc.h
  93. 16 4
      dtool/src/dtoolbase/memoryHook.I
  94. 5 0
      dtool/src/dtoolbase/memoryHook.cxx
  95. 3 17
      dtool/src/dtoolbase/mutexDummyImpl.I
  96. 9 5
      dtool/src/dtoolbase/mutexDummyImpl.h
  97. 8 10
      dtool/src/dtoolbase/mutexPosixImpl.I
  98. 15 1
      dtool/src/dtoolbase/mutexPosixImpl.h
  99. 2 10
      dtool/src/dtoolbase/mutexSpinlockImpl.I
  100. 6 2
      dtool/src/dtoolbase/mutexSpinlockImpl.h

+ 43 - 0
.gitignore

@@ -1,9 +1,52 @@
+# makepanda directories
 /built*/
 /built*/
 /thirdparty/
 /thirdparty/
 /targetroot/
 /targetroot/
 /dstroot/
 /dstroot/
+
+# Core dumps
 core
 core
 core.*
 core.*
 vgcore.*
 vgcore.*
+
+# Editor files/directories
 *.save
 *.save
 *.save.1
 *.save.1
+*.sublime-workspace
+.vscode/
+
+# Temporary build files
+/_vfsimporter.*
+*.pdb
+*.obj
+*.o
+*.gch
+*.pch
+
+# Produced installer/executables
+/*.exe
+/*.deb
+/*.rpm
+/*.app
+/*.pkg
+/*.dmg
+/*.whl
+
+# CMake
+/build/
+CMakeCache.txt
+CMakeFiles/
+CMakeScripts/
+Makefile
+cmake_install.cmake
+install_manifest.txt
+CTestTestfile.cmake
+
+# Windows
+Thumbs.db
+ehthumbs.db
+
+# Python
+__pycache__
+*.pyc
+*.pyo

+ 1 - 1
.travis.yml

@@ -3,7 +3,7 @@ sudo: false
 matrix:
 matrix:
   include:
   include:
     - compiler: gcc
     - compiler: gcc
-      env: PYTHONV=python2.7 FLAGS=
+      env: PYTHONV=python2.7 FLAGS=--optimize=4
     - compiler: clang
     - compiler: clang
       env: PYTHONV=python3 FLAGS=--installer
       env: PYTHONV=python3 FLAGS=--installer
     - compiler: clang
     - compiler: clang

+ 0 - 9
contrib/.gitignore

@@ -1,9 +0,0 @@
-*.pyc
-*.pyo
-/__init__.py
-# These are files that are generated within the source tree by the
-# ppremake system.
-Makefile
-pp.dep
-/built/
-Opt?-*

+ 0 - 2
contrib/src/panda3dtoolsgui/.gitignore

@@ -1,2 +0,0 @@
-/build
-/dist

+ 0 - 9
direct/.gitignore

@@ -1,9 +0,0 @@
-*.pyc
-*.pyo
-/__init__.py
-# These are files that are generated within the source tree by the
-# ppremake system.
-Makefile
-pp.dep
-/built/
-Opt?-*

+ 0 - 1
direct/src/configfiles/.gitignore

@@ -1 +0,0 @@
-/40_direct.prc

+ 0 - 3
direct/src/dcparser/.gitignore

@@ -1,3 +0,0 @@
-/dcLexer.cxx
-/dcParser.cxx
-/dcParser.h

+ 0 - 106
direct/src/directbase/ppython.cxx

@@ -1,106 +0,0 @@
-// This is a little wrapper to make it easy to run a python program from the
-// command line.  Basically, it just interfaces to the Python API and imports
-// the module that was specified by the IMPORT_MODULE preprocessor definition
-// when it was compiled.
-
-#include "dtoolbase.h"
-
-#undef _POSIX_C_SOURCE
-#undef _XOPEN_SOURCE
-#include <Python.h>
-#if PY_MAJOR_VERSION >= 3
-#include <wchar.h>
-#endif
-
-#ifndef IMPORT_MODULE
-#error IMPORT_MODULE must be defined when compiling ppython.cxx !
-#endif
-
-#define _STRINGIFY(s) #s
-#define STRINGIFY(s) _STRINGIFY(s)
-#define IMPORT_MODULE_STR STRINGIFY(IMPORT_MODULE)
-
-#if defined(_WIN32) && PY_MAJOR_VERSION >= 3
-// As Py_SetProgramName expects a wchar_t*, it's easiest to just use the wmain
-// entry point.
-int wmain(int argc, wchar_t *argv[]) {
-  Py_SetProgramName(argv[0]);
-
-#elif PY_MAJOR_VERSION >= 3
-// Convert from UTF-8 to wchar_t*.
-int main(int argc, char *mb_argv[]) {
-  wchar_t **argv = new wchar_t*[argc + 1];
-  for (int i = 0; i < argc; ++i) {
-    size_t len = mbstowcs(NULL, mb_argv[i], 0);
-    argv[i] = new wchar_t[len + 1];
-    mbstowcs(argv[i], mb_argv[i], len);
-    argv[i][len] = 0;
-  }
-  // Just for good measure
-  argv[argc] = NULL;
-
-  Py_SetProgramName(argv[0]);
-
-#else
-// Python 2.
-int main(int argc, char *argv[]) {
-  Py_SetProgramName(argv[0]);
-#endif
-
-  // On Windows, we need to set pythonhome correctly.  We'll try to find
-  // ppython.exe on the path and set pythonhome to its location.
-#ifdef _WIN32
-#if PY_MAJOR_VERSION >= 3
-  // Py_SetPythonHome expects a wchar_t in Python 3.
-  wchar_t *path = _wgetenv(L"PATH");
-  wchar_t *result = wcstok(path, L";");
-  while (result != NULL) {
-    struct _stat st;
-    wchar_t *ppython = (wchar_t*) malloc(wcslen(result) * 2 + 26);
-    wcscpy(ppython, result);
-    wcscat(ppython, L"\\python.exe");
-    if (_wstat(ppython, &st) == 0) {
-      Py_SetPythonHome(result);
-      free(ppython);
-      break;
-    }
-    result = wcstok(NULL, L";");
-    free(ppython);
-  }
-#else
-  char *path = getenv("PATH");
-  char *result = strtok(path, ";");
-  while (result != NULL) {
-    struct stat st;
-    char *ppython = (char*) malloc(strlen(result) + 13);
-    strcpy(ppython, result);
-    strcat(ppython, "\\ppython.exe");
-    if (stat(ppython, &st) == 0) {
-      Py_SetPythonHome(result);
-      free(ppython);
-      break;
-    }
-    result = strtok(NULL, ";");
-    free(ppython);
-  }
-#endif
-#endif
-
-  Py_Initialize();
-
-  if (Py_VerboseFlag) {
-    fprintf(stderr, "Python %s\\n%s\\n", Py_GetVersion(), Py_GetCopyright());
-  }
-
-  PySys_SetArgv(argc, argv);
-
-  int sts = 0;
-  PyObject* m = PyImport_ImportModule(IMPORT_MODULE_STR);
-  if (m <= 0) {
-    PyErr_Print();
-    sts = 1;
-  }
-
-  Py_Finalize();
-  return sts;
-}

+ 10 - 1
direct/src/directscripts/eggcacher.py

@@ -87,4 +87,13 @@ class EggCacher:
             TexturePool.releaseAllTextures()
             TexturePool.releaseAllTextures()
             progress += size
             progress += size
 
 
-cacher = EggCacher(sys.argv[1:])
+
+def main(args=None):
+    if args is None:
+        args = sys.argv[1:]
+
+    cacher = EggCacher(args)
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())

+ 0 - 831
direct/src/directscripts/packpanda.nsi

@@ -1,831 +0,0 @@
-; Panda3D installation script for the Nullsoft Installation System (NSIS).
-; Jon Parise <[email protected]>
-; with Ben Johnson <[email protected]>
-; with Jason Pratt <[email protected]>
-; mangled by Josh Yelon <[email protected]>
-
-; Caller needs to define these variables:
-;
-;   COMPRESSOR    - either zlib or lzma
-;   NAME          - name of what we're building                 (ie, "Panda3D" or "Airblade")
-;   SMDIRECTORY   - where to put this in the start menu         (ie, "Panda3D 1.1.0" or "Airblade 1.1.0")
-;   INSTALLDIR    - where to install the program                (ie, "C:\Program Files\Panda3D-1.1.0")
-;   OUTFILE       - where to put the output file                (ie, "..\nsis-output.exe")
-;   LICENSE       - location of the license file                (ie, "C:\Airblade\LICENSE.TXT")
-;   LANGUAGE      - name of the Language file to use            (ie, "English" or "Panda3DEnglish")
-;   RUNTEXT       - text for run-box at end of installation     (ie, "Run the Panda Greeting Card")
-;   IBITMAP       - name of installer bitmap                    (ie, "C:\Airblade\Airblade.bmp")
-;   UBITMAP       - name of uninstaller bitmap                  (ie, "C:\Airblade\Airblade.bmp")
-;
-;   PANDA         - location of panda install tree.
-;   PYVER         - version of Python that Panda was built with (ie, "2.7")
-;   PANDACONF     - name of panda config directory - usually $PANDA\etc 
-;   PSOURCE       - location of the panda source-tree if available, OR location of panda install tree.
-;   PYEXTRAS      - directory containing python extras, if any.
-;   REGVIEW       - either 32 or 64, depending on the build architecture.
-;
-;   PPGAME      - directory containing prepagaged game, if any        (ie, "C:\My Games\Airblade")
-;   PPMAIN      - python program containing prepackaged game, if any  (ie, "Airblade.py")
-;   PPICON      - file containing icon of prepackaged game.
-;
-
-!include "MUI.nsh"
-!include "WinMessages.nsh"
-Name "${NAME}"
-InstallDir "${INSTALLDIR}"
-OutFile "${OUTFILE}"
-
-SetCompress auto
-SetCompressor ${COMPRESSOR}
-
-!define MUI_WELCOMEFINISHPAGE_BITMAP "${IBITMAP}"
-!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${UBITMAP}"
-
-!define MUI_ABORTWARNING
-!define MUI_FINISHPAGE_NOREBOOTSUPPORT
-!define MUI_FINISHPAGE_RUN
-!define MUI_FINISHPAGE_RUN_FUNCTION runFunction
-!define MUI_FINISHPAGE_RUN_TEXT "${RUNTEXT}"
-
-!insertmacro MUI_PAGE_WELCOME
-!insertmacro MUI_PAGE_LICENSE "${LICENSE}"
-!insertmacro MUI_PAGE_DIRECTORY
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-
-!insertmacro MUI_UNPAGE_WELCOME
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-!insertmacro MUI_UNPAGE_FINISH
-
-!insertmacro MUI_LANGUAGE "${LANGUAGE}"
-
-ShowInstDetails nevershow
-ShowUninstDetails nevershow
-
-LicenseData "${LICENSE}"
-
-InstType "Typical"
-
-!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
-
-var READABLE
-var MANPAGE
-var TUTNAME
-
-Function runFunction
-        !ifdef PPGAME
-        ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk"
-        !else
-        ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk"
-        !endif
-FunctionEnd
-
-Section "${SMDIRECTORY}" SecCore
-        SectionIn 1 2 3 RO
-
-        SetDetailsPrint none
-        SetOutPath $INSTDIR
-        SetOverwrite try
-
-        SetOutPath $INSTDIR
-        File "${PANDA}\LICENSE"
-        SetOutPath $INSTDIR\bin
-        File /r "${PANDA}\bin\*.dll"
-        File /nonfatal /r "${PANDA}\bin\*.pyd"
-        File /nonfatal /r "${PANDA}\bin\Microsoft.*.manifest"
-        SetOutPath $INSTDIR\etc
-        File /r "${PANDACONF}\*"
-        SetOutPath $INSTDIR\direct\directscripts
-        File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\directscripts\*"
-        SetOutPath $INSTDIR\direct\filter
-        File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\filter\*.sha"
-        SetOutPath $INSTDIR\direct
-        File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\*.py"
-        Delete "$INSTDIR\panda3d.py"
-        Delete "$INSTDIR\panda3d.pyc"
-        Delete "$INSTDIR\panda3d.pyo"
-        SetOutPath $INSTDIR\pandac
-        File /r "${PANDA}\pandac\*.py"
-        SetOutPath $INSTDIR\panda3d
-        File /r "${PANDA}\panda3d\*.py"
-        File /r "${PANDA}\panda3d\*.pyd"
-        SetOutPath $INSTDIR\python
-        File /r "${PANDA}\python\*"
-        RMDir /r "$SMPROGRAMS\${SMDIRECTORY}"
-        CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}"
-
-        !ifdef PPGAME
-
-            SetOutPath $INSTDIR\models
-            File /r /x CVS "${PANDA}\models\*"
-            SetOutPath $INSTDIR\bin
-            File /r "${PANDA}\bin\eggcacher.exe"
-            SetOutpath $INSTDIR\game
-            File /r "${PPGAME}\*"
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk" "$INSTDIR\python\ppython.exe" "-E ${PPMAIN}" "$INSTDIR\${PPICON}" 0 SW_SHOWMINIMIZED "" "Play ${NAME}"
-            # Preload all EGG files into the model-cache
-            SetOutPath $INSTDIR
-            SetDetailsPrint textonly
-            SetDetailsView show
-            nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise game'
-            SetDetailsPrint none
-            SetDetailsView hide
-
-        !else
-
-            SetOutPath $INSTDIR\plugins
-            File /nonfatal /r "${PANDA}\plugins\*.dle"
-            File /nonfatal /r "${PANDA}\plugins\*.dlo"
-            File /nonfatal /r "${PANDA}\plugins\*.mll"
-            File /nonfatal /r "${PANDA}\plugins\*.mel"
-            File /nonfatal /r "${PANDA}\plugins\*.ms"
-            File "${PSOURCE}\doc\INSTALLING-PLUGINS.TXT"
-            SetOutPath $INSTDIR\pandac\input
-            File /r "${PANDA}\pandac\input\*"
-            SetOutPath $INSTDIR\bin
-            File /r "${PANDA}\bin\*.exe"
-            File /nonfatal /r "${PANDA}\bin\*.p3d"
-            SetOutPath $INSTDIR\lib
-            File /r /x *.exp "${PANDA}\lib\*"
-            SetOutPath $INSTDIR\include
-            File /r /x *.exp "${PANDA}\include\*"
-            SetOutPath $INSTDIR\Pmw
-            File /r /x CVS "${PANDA}\Pmw\*"
-            SetOutPath $INSTDIR\NSIS
-            File /r /x CVS "${NSISDIR}\*"
-            SetOutPath $INSTDIR
-            File /r /x CVS "${PANDA}\ReleaseNotes"
-            !ifdef PYEXTRAS
-            SetOutPath $INSTDIR\python\lib
-            File /nonfatal /r "${PYEXTRAS}\*"
-            !endif
-            SetOutPath $INSTDIR\models
-            File /r /x CVS "${PANDA}\models\*"
-            SetOutPath $INSTDIR\samples
-            File /nonfatal /r /x CVS "${PSOURCE}\samples\*"
-            MessageBox MB_YESNO|MB_ICONQUESTION \
-               "EGG caching is about to begin.$\nThis process may take a couple minute and approximately 270 MB of RAM.$\nWARNING : It might stuck if your computer resources are low.$\n$\nDo you really want to do this optional step ?" \
-               IDNO SkipCaching
-            # Preload all EGG files into the model-cache
-            SetOutPath $INSTDIR
-            SetDetailsPrint both
-            SetDetailsView show
-            nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise models samples'
-            SetDetailsPrint none
-            SetDetailsView hide
-            SkipCaching:
-
-            SetOutPath $INSTDIR
-            WriteINIStr $INSTDIR\Website.url "InternetShortcut" "URL" "http://panda3d.org/"
-            WriteINIStr $INSTDIR\Manual.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php"
-            WriteINIStr $INSTDIR\Samples.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs_in_the_Distribution"
-            SetOutPath $INSTDIR
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Manual"
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Website"
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Sample Program Manual"
-
-            FindFirst $0 $1 $INSTDIR\samples\*
-            loop:
-                StrCmp $1 "" done
-                StrCmp $1 "." next
-                StrCmp $1 ".." next
-    Push $1
-          Push "-"
-                Push " "
-                Call StrRep
-                Pop $R0
-                StrCpy $READABLE $R0
-    Push $1
-          Push "-"
-                Push "_"
-                Call StrRep
-                Pop $R0
-                StrCpy $MANPAGE $R0
-                CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE"
-                SetOutPath $INSTDIR\samples\$1
-                WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE"
-                CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Manual Entry on this Sample Program"
-                CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\View Source Code.lnk" "$INSTDIR\samples\$1"
-                FindFirst $2 $3 $INSTDIR\samples\$1\Tut-*.py
-                iloop:
-                    StrCmp $3 "" idone
-                    StrCpy $TUTNAME $3 -3 4
-                    Push $TUTNAME
-                    Push "-"
-                    Push " "
-                    Call StrRep
-                    Pop $R0
-                    StrCpy $TUTNAME $R0
-                    CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME"
-                    CreateShortCut "$INSTDIR\samples\$1\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME"
-                    FindNext $2 $3
-                    goto iloop
-                idone:
-            next:
-                FindNext $0 $1
-                Goto loop
-            done:
-
-        !endif
-
-SectionEnd
-
-
-Section -post
-
-        !ifdef REGVIEW
-        SetRegView ${REGVIEW}
-        !endif
-
-        !ifndef PPGAME
-
-        # Add the "bin" directory to the PATH.
-        Push "$INSTDIR\python"
-        Call RemoveFromPath
-        Push "$INSTDIR\python\Scripts"
-        Call RemoveFromPath
-        Push "$INSTDIR\bin"
-        Call RemoveFromPath
-        Push "$INSTDIR\python"
-        Call AddToPath
-        Push "$INSTDIR\python\Scripts"
-        Call AddToPath
-        Push "$INSTDIR\bin"
-        Call AddToPath
-
-        ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp $0 "$INSTDIR\python" RegPath 0
-        StrCmp $0 "" RegPath 0
-
-        MessageBox MB_YESNO|MB_ICONQUESTION \
-                "Your system already has a copy of Python installed. Panda3D installs its own copy of Python ${PYVER}, which will install alongside your existing copy. Would you like to make Panda's copy the default Python? If you choose 'No', you will have to configure your existing copy of Python to use the Panda3D libraries, keeping in mind that this version of Panda3D can only run with Python ${PYVER}." \
-                IDNO SkipRegPath
-
-        RegPath:
-        DetailPrint "Adding registry keys for python..."
-        WriteRegStr HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" "" "$INSTDIR\python"
-        SkipRegPath:
-        !endif
-
-        DetailPrint "Adding the uninstaller ..."
-        Delete "$INSTDIR\uninst.exe"
-        WriteUninstaller "$INSTDIR\uninst.exe"
-        WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "DisplayName" "${SMDIRECTORY}"
-        WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "UninstallString" '"$INSTDIR\uninst.exe"'
-        SetOutPath $INSTDIR
-        CreateShortcut "$SMPROGRAMS\${SMDIRECTORY}\Uninstall ${NAME}.lnk" "$INSTDIR\uninst.exe" ""
-
-SectionEnd
-
-Section Uninstall
-
-        !ifdef REGVIEW
-        SetRegView ${REGVIEW}
-        !endif
-
-        !ifndef PPGAME
-        Push "$INSTDIR\python"
-        Call un.RemoveFromPath
-        Push "$INSTDIR\python\Scripts"
-        Call un.RemoveFromPath
-        Push "$INSTDIR\bin"
-        Call un.RemoveFromPath
-
-        ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp $0 "$INSTDIR\python" 0 SkipUnReg
-        DeleteRegKey HKLM "Software\Python\PythonCore\${PYVER}"
-        SkipUnReg:
-        !endif
-
-        Delete "$INSTDIR\uninst.exe"
-        RMDir /r "$SMPROGRAMS\${SMDIRECTORY}"
-        RMDir /r "$INSTDIR"
-        DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}"
-
-SectionEnd
-
-# --[ Utility Functions ]------------------------------------------------------
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function IsNT
-        Push $0
-        ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
-        StrCmp $0 "" 0 IsNT_yes
-        ; we are not NT.
-        Pop $0
-        Push 0
-        Return
-        IsNT_yes:
-                ; NT!!!
-                Pop $0
-                Push 1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function un.IsNT
-        Push $0
-        ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
-        StrCmp $0 "" 0 unIsNT_yes
-        ; we are not NT.
-        Pop $0
-        Push 0
-        Return
-        unIsNT_yes:
-                ; NT!!!
-                Pop $0
-                Push 1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function StrStr
-        Push $0
-        Exch
-        Pop $0 ; $0 now have the string to find
-        Push $1
-        Exch 2
-        Pop $1 ; $1 now have the string to find in
-        Exch
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        StrCpy $2 -1
-        StrLen $3 $0
-        StrLen $4 $1
-        IntOp $4 $4 - $3
-        unStrStr_loop:
-                IntOp $2 $2 + 1
-                IntCmp $2 $4 0 0 unStrStrReturn_notFound
-                StrCpy $5 $1 $3 $2
-                StrCmp $5 $0 unStrStr_done unStrStr_loop
-        unStrStrReturn_notFound:
-                StrCpy $2 -1
-        unStrStr_done:
-                Pop $5
-                Pop $4
-                Pop $3
-                Exch $2
-                Exch 2
-                Pop $0
-                Pop $1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function un.StrStr
-        Push $0
-        Exch
-        Pop $0 ; $0 now have the string to find
-        Push $1
-        Exch 2
-        Pop $1 ; $1 now have the string to find in
-        Exch
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        StrCpy $2 -1
-        StrLen $3 $0
-        StrLen $4 $1
-        IntOp $4 $4 - $3
-        unStrStr_loop:
-                IntOp $2 $2 + 1
-                IntCmp $2 $4 0 0 unStrStrReturn_notFound
-                StrCpy $5 $1 $3 $2
-                StrCmp $5 $0 unStrStr_done unStrStr_loop
-        unStrStrReturn_notFound:
-                StrCpy $2 -1
-        unStrStr_done:
-                Pop $5
-                Pop $4
-                Pop $3
-                Exch $2
-                Exch 2
-                Pop $0
-                Pop $1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-; Commentary and smarter ';' checking by Jon Parise <[email protected]>
-Function AddToPath
-        Exch $0
-        Push $1
-        Push $2
-        Push $3
-        Call IsNT
-        Pop $1
-
-        StrCmp $1 1 AddToPath_NT
-                ; We're not on NT, so modify the AUTOEXEC.BAT file.
-                StrCpy $1 $WINDIR 2
-                FileOpen $1 "$1\autoexec.bat" a
-                FileSeek $1 0 END
-                GetFullPathName /SHORT $0 $0
-                FileWrite $1 "$\r$\nSET PATH=%PATH%;$0$\r$\n"
-                FileClose $1
-                Goto AddToPath_done
-        
-        AddToPath_NT:
-                ReadRegStr $1 HKCU "Environment" "PATH"
-                Call IsUserAdmin
-                Pop $3
-                ; If this is an Admin user, use the System env. variable instead of the user's env. variable
-                StrCmp $3 1 0 +2
-                        ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-
-                ; If the PATH string is empty, jump over the mangling routines.
-                StrCmp $1 "" AddToPath_NTdoIt
-
-                ; Pull off the last character of the PATH string.  If it's a semicolon,
-                ; we don't need to add another one, so jump to the section where we
-                ; append the new PATH component(s).
-                StrCpy $2 $1 1 -1
-                StrCmp $2 ";" AddToPath_NTAddPath AddToPath_NTAddSemi
-
-                AddToPath_NTAddSemi:
-                        StrCpy $1 "$1;"
-                        Goto AddToPath_NTAddPath
-                AddToPath_NTAddPath:
-                        StrCpy $0 "$1$0"
-                        Goto AddToPath_NTdoIt
-                AddToPath_NTdoIt:
-                        Call IsUserAdmin
-                        Pop $3
-                        StrCmp $3 1 0 NotAdmin
-                                WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0
-                                Goto AddToPath_done
-                        
-                        NotAdmin:
-                                WriteRegExpandStr HKCU "Environment" "PATH" $0
-        AddToPath_done:
-                SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-                Pop $3
-                Pop $2
-                Pop $1
-                Pop $0
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function RemoveFromPath
-        Exch $0
-        Push $1
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        Call IsNT
-        Pop $1
-        StrCmp $1 1 unRemoveFromPath_NT
-                ; Not on NT
-                StrCpy $1 $WINDIR 2
-                FileOpen $1 "$1\autoexec.bat" r
-                GetTempFileName $4
-                FileOpen $2 $4 w
-                GetFullPathName /SHORT $0 $0
-                StrCpy $0 "SET PATH=%PATH%;$0"
-                SetRebootFlag true
-                Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoop:
-                        FileRead $1 $3
-                        StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0" unRemoveFromPath_dosLoop
-                        StrCmp $3 "" unRemoveFromPath_dosLoopEnd
-                        FileWrite $2 $3
-                        Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoopEnd:
-                        FileClose $2
-                        FileClose $1
-                        StrCpy $1 $WINDIR 2
-                        Delete "$1\autoexec.bat"
-                        CopyFiles /SILENT $4 "$1\autoexec.bat"
-                        Delete $4
-                        Goto unRemoveFromPath_done
-
-                unRemoveFromPath_NT:
-                        StrLen $2 $0
-                        Call IsUserAdmin
-                        Pop $5
-                        StrCmp $5 1 0 NotAdmin
-                                ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-                                        Goto unRemoveFromPath_done
-                        
-                        
-                        NotAdmin:               
-                                ReadRegStr $1 HKCU "Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKCU "Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-
-                unRemoveFromPath_done:
-                        Pop $5
-                        Pop $4
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function un.RemoveFromPath
-        Exch $0
-        Push $1
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        Call un.IsNT
-        Pop $1
-        StrCmp $1 1 unRemoveFromPath_NT
-                ; Not on NT
-                StrCpy $1 $WINDIR 2
-                FileOpen $1 "$1\autoexec.bat" r
-                GetTempFileName $4
-                FileOpen $2 $4 w
-                GetFullPathName /SHORT $0 $0
-                StrCpy $0 "SET PATH=%PATH%;$0"
-                SetRebootFlag true
-                Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoop:
-                        FileRead $1 $3
-                        StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0" unRemoveFromPath_dosLoop
-                        StrCmp $3 "" unRemoveFromPath_dosLoopEnd
-                        FileWrite $2 $3
-                        Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoopEnd:
-                        FileClose $2
-                        FileClose $1
-                        StrCpy $1 $WINDIR 2
-                        Delete "$1\autoexec.bat"
-                        CopyFiles /SILENT $4 "$1\autoexec.bat"
-                        Delete $4
-                        Goto unRemoveFromPath_done
-
-                unRemoveFromPath_NT:
-                        StrLen $2 $0
-                        Call un.IsUserAdmin
-                        Pop $5
-                        StrCmp $5 1 0 NotAdmin
-                                ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call un.StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-                                        Goto unRemoveFromPath_done
-                        
-                        
-                        NotAdmin:               
-                                ReadRegStr $1 HKCU "Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call un.StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKCU "Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-
-                unRemoveFromPath_done:
-                        Pop $5
-                        Pop $4
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/nsisweb.php?page=329&instances=0,11
-; Localized by Ben Johnson ([email protected])
-Function IsUserAdmin
-        Push $0
-        Push $1
-        Push $2
-        Push $3
-        Call IsNT
-        Pop $1
-
-        ClearErrors
-        UserInfo::GetName
-        ;IfErrors Win9x
-        Pop $2
-        UserInfo::GetAccountType
-        Pop $3
-
-        ; Compare results of IsNT with "1"
-        StrCmp $1 1 0 NotNT
-                ;This is NT
-                
-
-                StrCmp $3 "Admin" 0 NotAdmin
-                        ; Observation: I get here when running Win98SE. (Lilla)
-                        ; The functions UserInfo.dll looks for are there on Win98 too, 
-                        ; but just don't work. So UserInfo.dll, knowing that admin isn't required
-                        ; on Win98, returns admin anyway. (per kichik)
-                        ; MessageBox MB_OK 'User "$R1" is in the Administrators group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 1
-                        Return
-
-                NotAdmin:
-                        ; You should still check for an empty string because the functions
-                        ; UserInfo.dll looks for may not be present on Windows 95. (per kichik)
-                
-                        #StrCmp $2 "" Win9x
-                        #StrCpy $0 0
-                        ;MessageBox MB_OK 'User "$2" is in the "$3" group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 0
-                        Return
-
-        ;Because we use IsNT, this is redundant.
-        #Win9x:
-        #       ; comment/message below is by UserInfo.nsi author:
-        #       ; This one means you don't need to care about admin or
-        #       ; not admin because Windows 9x doesn't either
-        #       ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
-        #       StrCpy $0 0
-
-        NotNT:
-                ;We are not NT
-                ;Win9x doesn't have "admin" users.
-                ;Let the user do whatever.
-                Pop $3
-                Pop $2
-                Pop $1
-                Pop $0
-
-                Push 1
-
-FunctionEnd
-
-Function un.IsUserAdmin
-        Push $0
-        Push $1
-        Push $2
-        Push $3
-        Call un.IsNT
-        Pop $1
-
-        ClearErrors
-        UserInfo::GetName
-        ;IfErrors Win9x
-        Pop $2
-        UserInfo::GetAccountType
-        Pop $3
-
-        ; Compare results of IsNT with "1"
-        StrCmp $1 1 0 NotNT
-                ;This is NT
-                
-
-                StrCmp $3 "Admin" 0 NotAdmin
-                        ; Observation: I get here when running Win98SE. (Lilla)
-                        ; The functions UserInfo.dll looks for are there on Win98 too, 
-                        ; but just don't work. So UserInfo.dll, knowing that admin isn't required
-                        ; on Win98, returns admin anyway. (per kichik)
-                        ; MessageBox MB_OK 'User "$R1" is in the Administrators group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 1
-                        Return
-
-                NotAdmin:
-                        ; You should still check for an empty string because the functions
-                        ; UserInfo.dll looks for may not be present on Windows 95. (per kichik)
-                
-                        #StrCmp $2 "" Win9x
-                        #StrCpy $0 0
-                        ;MessageBox MB_OK 'User "$2" is in the "$3" group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 0
-                        Return
-
-        ;Because we use IsNT, this is redundant.
-        #Win9x:
-        #       ; comment/message below is by UserInfo.nsi author:
-        #       ; This one means you don't need to care about admin or
-        #       ; not admin because Windows 9x doesn't either
-        #       ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
-        #       StrCpy $0 0
-
-        NotNT:
-                ;We are not NT
-                ;Win9x doesn't have "admin" users.
-                ;Let the user do whatever.
-                Pop $3
-                Pop $2
-                Pop $1
-                Pop $0
-
-                Push 1
-
-FunctionEnd
-
-Function StrRep
-
-  ;Written by dirtydingus 2003-02-20 04:30:09 
-  ; USAGE
-  ;Push String to do replacement in (haystack)
-  ;Push String to replace (needle)
-  ;Push Replacement
-  ;Call StrRep
-  ;Pop $R0 result
-  ;StrCpy $Result STR $R0
-
-  Exch $R4 ; $R4 = Replacement String
-  Exch
-  Exch $R3 ; $R3 = String to replace (needle)
-  Exch 2
-  Exch $R1 ; $R1 = String to do replacement in (haystack)
-  Push $R2 ; Replaced haystack
-  Push $R5 ; Len (needle)
-  Push $R6 ; len (haystack)
-  Push $R7 ; Scratch reg
-  StrCpy $R2 ""
-  StrLen $R5 $R3
-  StrLen $R6 $R1
-loop:
-  StrCpy $R7 $R1 $R5
-  StrCmp $R7 $R3 found
-  StrCpy $R7 $R1 1 ; - optimization can be removed if U know len needle=1
-  StrCpy $R2 "$R2$R7"
-  StrCpy $R1 $R1 $R6 1
-  StrCmp $R1 "" done loop
-found:
-  StrCpy $R2 "$R2$R4"
-  StrCpy $R1 $R1 $R6 $R5
-  StrCmp $R1 "" done loop
-done:
-  StrCpy $R3 $R2
-  Pop $R7
-  Pop $R6
-  Pop $R5
-  Pop $R2
-  Pop $R1
-  Pop $R4
-  Exch $R3
-  
-FunctionEnd
-

+ 0 - 421
direct/src/directscripts/packpanda.py

@@ -1,421 +0,0 @@
-#############################################################################
-#
-# packpanda - this is a tool that packages up a panda game into a
-# convenient, easily-downloaded windows executable.  Packpanda runs on linux
-# and windows - on linux, it builds .debs and .rpms, on windows it relies on
-# NSIS, the nullsoft scriptable install system, to do the hard work.
-#
-# This is intentionally a very simplistic game-packer with very
-# limited options.  The goal is simplicity, not feature richness.
-# There are dozens of complex, powerful packaging tools already out
-# there.  This one is for people who just want to do it quick and
-# easy.
-#
-##############################################################################
-
-import sys, os, getopt, shutil, py_compile, subprocess
-
-OPTIONLIST = [
-("dir",       1, "Name of directory containing game"),
-("name",      1, "Human-readable name of the game"),
-("version",   1, "Version number to add to game name"),
-("rmdir",     2, "Delete all directories with given name"),
-("rmext",     2, "Delete all files with given extension"),
-("fast",      0, "Use fast compression instead of good compression"),
-("bam",       0, "Generate BAM files, change default-model-extension to BAM"),
-("pyc",       0, "Generate PYC files"),
-]
-
-def ParseFailure():
-  print("")
-  print("packpanda usage:")
-  print("")
-  for (opt, hasval, explanation) in OPTIONLIST:
-    if (hasval):
-      print("  --%-10s    %s"%(opt+" x", explanation))
-    else:
-      print("  --%-10s    %s"%(opt+"  ", explanation))
-  sys.exit(1)
-
-def ParseOptions(args):
-  try:
-    options = {}
-    longopts = []
-    for (opt, hasval, explanation) in OPTIONLIST:
-      if (hasval==2):
-        longopts.append(opt+"=")
-        options[opt] = []
-      elif (hasval==1):
-        longopts.append(opt+"=")
-        options[opt] = ""
-      else:
-        longopts.append(opt)
-        options[opt] = 0
-    opts, extras = getopt.getopt(args, "", longopts)
-    for option, value in opts:
-      for (opt, hasval, explanation) in OPTIONLIST:
-        if (option == "--"+opt):
-          if (hasval==2): options[opt].append(value)
-          elif (hasval==1): options[opt] = value
-          else: options[opt] = 1
-    return options
-  except: ParseFailure();
-
-OPTIONS = ParseOptions(sys.argv[1:])
-
-##############################################################################
-#
-# Locate the relevant trees.
-#
-##############################################################################
-
-PANDA=None
-for dir in sys.path:
-    if (dir != "") and os.path.exists(os.path.join(dir,"direct")) and os.path.exists(os.path.join(dir,"pandac")):
-        PANDA=os.path.abspath(dir)
-if (PANDA is None):
-  sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).")
-print("PANDA located at "+PANDA)
-
-if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (sys.platform != "win32" or os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))):
-  PSOURCE=os.path.abspath(os.path.join(PANDA,".."))
-  if (sys.platform == "win32"):
-    NSIS=os.path.abspath(os.path.join(PANDA,"..","thirdparty","win-nsis"))
-else:
-  PSOURCE=PANDA
-  if (sys.platform == "win32"):
-    NSIS=os.path.join(PANDA,"nsis")
-
-##############################################################################
-#
-# Identify the main parts of the game: DIR, NAME, MAIN, ICON, BITMAP, etc
-#
-##############################################################################
-
-VER=OPTIONS["version"]
-DIR=OPTIONS["dir"]
-if (DIR==""):
-  print("You must specify the --dir option.")
-  ParseFailure()
-DIR=os.path.abspath(DIR)
-MYDIR=os.path.abspath(os.getcwd())
-BASENAME=os.path.basename(DIR)
-if (OPTIONS["name"] != ""):
-  NAME=OPTIONS["name"]
-else:
-  NAME=BASENAME
-SMDIRECTORY=NAME
-if (VER!=""): SMDIRECTORY=SMDIRECTORY+" "+VER
-PYTHONV="python"+sys.version[:3]
-LICENSE=os.path.join(DIR, "license.txt")
-OUTFILE=os.path.basename(DIR)
-if (VER!=""): OUTFILE=OUTFILE+"-"+VER
-if (sys.platform == "win32"):
-  ICON=os.path.join(DIR, "icon.ico")
-  BITMAP=os.path.join(DIR, "installer.bmp")
-  OUTFILE=os.path.abspath(OUTFILE+".exe")
-  INSTALLDIR='C:\\'+os.path.basename(DIR)
-  if (VER!=""): INSTALLDIR=INSTALLDIR+"-"+VER
-  COMPRESS="lzma"
-  if (OPTIONS["fast"]): COMPRESS="zlib"
-if (OPTIONS["pyc"]): MAIN="main.pyc"
-else: MAIN="main.py"
-
-def PrintFileStatus(label, file):
-  if (os.path.exists(file)):
-    print("%-15s: %s"%(label, file))
-  else:
-    print("%-15s: %s (MISSING)"%(label, file))
-
-PrintFileStatus("Dir", DIR)
-print("%-15s: %s"%("Name", NAME))
-print("%-15s: %s"%("Start Menu", SMDIRECTORY))
-PrintFileStatus("Main", os.path.join(DIR, MAIN))
-if (sys.platform == "win32"):
-  PrintFileStatus("Icon", ICON)
-  PrintFileStatus("Bitmap", BITMAP)
-PrintFileStatus("License", LICENSE)
-print("%-15s: %s"%("Output", OUTFILE))
-if (sys.platform == "win32"):
-  print("%-15s: %s"%("Install Dir", INSTALLDIR))
-
-if (os.path.isdir(DIR)==0):
-  sys.exit("Difficulty reading "+DIR+". Cannot continue.")
-
-if (os.path.isfile(os.path.join(DIR, "main.py"))==0):
-  sys.exit("Difficulty reading main.py. Cannot continue.")
-
-if (os.path.isfile(LICENSE)==0):
-  LICENSE=os.path.join(PANDA,"LICENSE")
-
-if (sys.platform == "win32") and (os.path.isfile(BITMAP)==0):
-  BITMAP=os.path.join(NSIS,"Contrib","Graphics","Wizard","nsis.bmp")
-
-if (sys.platform == "win32"):
-  if (os.path.isfile(ICON)==0):
-    PPICON="bin\\ppython.exe"
-  else:
-    PPICON="game\\icon.ico"
-
-##############################################################################
-#
-# Copy the game to a temporary directory, so we can modify it safely.
-#
-##############################################################################
-
-def limitedCopyTree(src, dst, rmdir):
-    if (os.path.isdir(src)):
-        if (os.path.basename(src) in rmdir):
-            return
-        if (not os.path.isdir(dst)): os.mkdir(dst)
-        for x in os.listdir(src):
-            limitedCopyTree(os.path.join(src,x), os.path.join(dst,x), rmdir)
-    else:
-        shutil.copyfile(src, dst)
-
-
-TMPDIR=os.path.abspath("packpanda-TMP")
-if (sys.platform == "win32"):
-  TMPGAME=os.path.join(TMPDIR,"game")
-  TMPETC=os.path.join(TMPDIR,"etc")
-else:
-  TMPGAME=os.path.join(TMPDIR,"usr","share","games",BASENAME,"game")
-  TMPETC=os.path.join(TMPDIR,"usr","share","games",BASENAME,"etc")
-print("")
-print("Copying the game to "+TMPDIR+"...")
-if (os.path.exists(TMPDIR)):
-    try: shutil.rmtree(TMPDIR)
-    except: sys.exit("Cannot delete "+TMPDIR)
-try:
-    os.mkdir(TMPDIR)
-    rmdir = {}
-    for x in OPTIONS["rmdir"]:
-        rmdir[x] = 1
-    if not os.path.isdir( TMPGAME ):
-        os.makedirs(TMPGAME)
-    limitedCopyTree(DIR, TMPGAME, rmdir)
-    if not os.path.isdir( TMPETC ):
-        os.makedirs(TMPETC)
-    if sys.platform == "win32":
-      limitedCopyTree(os.path.join(PANDA, "etc"), TMPETC, {})
-    else:
-      shutil.copyfile("/etc/Config.prc", os.path.join(TMPETC, "Config.prc"))
-      shutil.copyfile("/etc/Confauto.prc", os.path.join(TMPETC, "Confauto.prc"))
-except: sys.exit("Cannot copy game to "+TMPDIR)
-
-##############################################################################
-#
-# If --bam requested, change default-model-extension .egg to bam.
-#
-##############################################################################
-
-def ReadFile(wfile):
-    try:
-        srchandle = open(wfile, "rb")
-        data = srchandle.read()
-        srchandle.close()
-        return data
-    except: exit("Cannot read "+wfile)
-
-def WriteFile(wfile,data):
-    try:
-        dsthandle = open(wfile, "wb")
-        dsthandle.write(data)
-        dsthandle.close()
-    except: exit("Cannot write "+wfile)
-
-if OPTIONS["bam"]:
-    CONF=ReadFile(os.path.join(TMPETC,"Confauto.prc"))
-    CONF=CONF.replace("default-model-extension .egg","default-model-extension .bam")
-    WriteFile(os.path.join(TMPETC,"Confauto.prc"), CONF)
-
-##############################################################################
-#
-# Compile all py files, convert all egg files.
-#
-# We do this as a sanity check, even if the user
-# hasn't requested that his files be compiled.
-#
-##############################################################################
-
-if (sys.platform == "win32"):
-  EGG2BAM=os.path.join(PANDA,"bin","egg2bam.exe")
-else:
-  EGG2BAM=os.path.join(PANDA,"bin","egg2bam")
-
-def egg2bam(file,bam):
-    present = os.path.exists(bam)
-    if (present): bam = "packpanda-TMP.bam";
-    cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"'
-    print("Executing: "+cmd)
-    if (sys.platform == "win32"):
-      res = os.spawnl(os.P_WAIT, EGG2BAM, cmd)
-    else:
-      res = os.system(cmd)
-    if (res != 0): sys.exit("Problem in egg file: "+file)
-    if (present) or (OPTIONS["bam"]==0):
-        os.unlink(bam)
-
-def py2pyc(file):
-    print("Compiling python "+file)
-    pyc = file[:-3]+'.pyc'
-    pyo = file[:-3]+'.pyo'
-    if (os.path.exists(pyc)): os.unlink(pyc)
-    if (os.path.exists(pyo)): os.unlink(pyo)
-    try: py_compile.compile(file)
-    except: sys.exit("Cannot compile "+file)
-    if (OPTIONS["pyc"]==0):
-        if (os.path.exists(pyc)):
-            os.unlink(pyc)
-        if (os.path.exists(pyo)):
-            os.unlink(pyo)
-
-def CompileFiles(file):
-    if (os.path.isfile(file)):
-        if (file.endswith(".egg")):
-            egg2bam(file, file[:-4]+'.bam')
-        elif (file.endswith(".egg.pz") or file.endswith(".egg.gz")):
-            egg2bam(file, file[:-7]+'.bam')
-        elif (file.endswith(".py")):
-            py2pyc(file)
-        else: pass
-    elif (os.path.isdir(file)):
-        for x in os.listdir(file):
-            CompileFiles(os.path.join(file, x))
-
-def DeleteFiles(file):
-    base = os.path.basename(file).lower()
-    if (os.path.isdir(file)):
-        for pattern in OPTIONS["rmdir"]:
-            if pattern.lower() == base:
-                print("Deleting "+file)
-                shutil.rmtree(file)
-                return
-        for x in os.listdir(file):
-            DeleteFiles(os.path.join(file, x))
-    else:
-        for ext in OPTIONS["rmext"]:
-            if base[-(len(ext) + 1):] == ("." + ext).lower():
-                print("Deleting "+file)
-                os.unlink(file)
-                return
-
-print("")
-print("Compiling BAM and PYC files...")
-os.chdir(TMPGAME)
-CompileFiles(".")
-DeleteFiles(".")
-
-##############################################################################
-#
-# Now make the installer. Yay!
-#
-##############################################################################
-
-INSTALLER_DEB_FILE="""
-Package: BASENAME
-Version: VERSION
-Section: games
-Priority: optional
-Architecture: ARCH
-Essential: no
-Depends: PYTHONV
-Provides: BASENAME
-Description: NAME
-Maintainer: Unknown
-"""
-
-INSTALLER_SPEC_FILE="""
-Summary: NAME
-Name: BASENAME
-Version: VERSION
-Release: 1
-Group: Amusement/Games
-License: See license file
-BuildRoot: TMPDIR
-BuildRequires: PYTHONV
-%description
-NAME
-%files
-%defattr(-,root,root)
-/usr/bin/BASENAME
-/usr/lib/games/BASENAME
-/usr/share/games/BASENAME
-"""
-
-RUN_SCRIPT="""
-#!/bin/sh
-cd /usr/share/games/BASENAME/game
-PYTHONPATH=/usr/lib/games/BASENAME:/usr/share/games/BASENAME
-LD_LIBRARY_PATH=/usr/lib/games/BASENAME
-PYTHONV MAIN
-"""
-
-if (sys.platform == "win32"):
-    CMD="\""+NSIS+"\\makensis.exe\" /V2 "
-    CMD=CMD+'/DCOMPRESSOR="'+COMPRESS+'" '
-    CMD=CMD+'/DNAME="'+NAME+'" '
-    CMD=CMD+'/DSMDIRECTORY="'+SMDIRECTORY+'" '
-    CMD=CMD+'/DINSTALLDIR="'+INSTALLDIR+'" '
-    CMD=CMD+'/DOUTFILE="'+OUTFILE+'" '
-    CMD=CMD+'/DLICENSE="'+LICENSE+'" '
-    CMD=CMD+'/DLANGUAGE="English" '
-    CMD=CMD+'/DRUNTEXT="Play '+NAME+'" '
-    CMD=CMD+'/DIBITMAP="'+BITMAP+'" '
-    CMD=CMD+'/DUBITMAP="'+BITMAP+'" '
-    CMD=CMD+'/DPANDA="'+PANDA+'" '
-    CMD=CMD+'/DPANDACONF="'+TMPETC+'" '
-    CMD=CMD+'/DPSOURCE="'+PSOURCE+'" '
-    CMD=CMD+'/DPPGAME="'+TMPGAME+'" '
-    CMD=CMD+'/DPPMAIN="'+MAIN+'" '
-    CMD=CMD+'/DPPICON="'+PPICON+'" '
-    CMD=CMD+'"'+PSOURCE+'\\direct\\directscripts\\packpanda.nsi"'
-
-    print("")
-    print(CMD)
-    print("packing...")
-    subprocess.call(CMD)
-else:
-    os.chdir(MYDIR)
-    os.system("mkdir -p %s/usr/bin" % TMPDIR)
-    os.system("mkdir -p %s/usr/share/games/%s" % (TMPDIR, BASENAME))
-    os.system("mkdir -p %s/usr/lib/games/%s" % (TMPDIR, BASENAME))
-    os.system("cp --recursive %s/direct          %s/usr/share/games/%s/direct" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp --recursive %s/pandac          %s/usr/share/games/%s/pandac" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp --recursive %s/models          %s/usr/share/games/%s/models" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp --recursive %s/Pmw             %s/usr/share/games/%s/Pmw" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp %s                             %s/usr/share/games/%s/LICENSE" % (LICENSE, TMPDIR, BASENAME))
-    os.system("cp --recursive /usr/lib/panda3d/* %s/usr/lib/games/%s/" % (TMPDIR, BASENAME))
-
-    # Make the script to run the game
-    txt = RUN_SCRIPT[1:].replace("BASENAME",BASENAME).replace("PYTHONV",PYTHONV).replace("MAIN",MAIN)
-    WriteFile(TMPDIR+"/usr/bin/"+BASENAME, txt)
-    os.system("chmod +x "+TMPDIR+"/usr/bin/"+BASENAME)
-
-    if (os.path.exists("/usr/bin/rpmbuild")):
-        os.system("rm -rf %s/DEBIAN" % TMPDIR)
-        os.system("rpm -E '%_target_cpu' > packpanda-TMP.txt")
-        ARCH=ReadFile("packpanda-TMP.txt").strip()
-        os.remove("packpanda-TMP.txt")
-        txt = INSTALLER_SPEC_FILE[1:].replace("VERSION",VER).replace("TMPDIR",TMPDIR)
-        txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("PYTHONV",PYTHONV)
-        WriteFile("packpanda-TMP.spec", txt)
-        os.system("rpmbuild --define '_rpmdir "+TMPDIR+"' -bb packpanda-TMP.spec")
-        os.system("mv "+ARCH+"/"+BASENAME+"-"+VER+"-1."+ARCH+".rpm .")
-        os.rmdir(ARCH)
-        os.remove("packpanda-TMP.spec")
-
-    if (os.path.exists("/usr/bin/dpkg-deb")):
-        os.system("dpkg --print-architecture > packpanda-TMP.txt")
-        ARCH=ReadFile("packpanda-TMP.txt").strip()
-        os.remove("packpanda-TMP.txt")
-        txt = INSTALLER_DEB_FILE[1:].replace("VERSION",str(VER)).replace("PYTHONV",PYTHONV)
-        txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("ARCH",ARCH)
-        os.system("mkdir -p %s/DEBIAN" % TMPDIR)
-        os.system("cd %s ; (find usr -type f -exec md5sum {} \;) >  DEBIAN/md5sums" % TMPDIR)
-        WriteFile(TMPDIR+"/DEBIAN/control",txt)
-        os.system("dpkg-deb -b "+TMPDIR+" "+BASENAME+"_"+VER+"_"+ARCH+".deb")
-
-    if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")):
-        exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!")
-

+ 1 - 1
direct/src/directtools/DirectCameraControl.py

@@ -413,7 +413,7 @@ class DirectCameraControl(DirectObject):
                 np = NodePath('temp')
                 np = NodePath('temp')
                 np.setPos(base.direct.camera, hitPt)
                 np.setPos(base.direct.camera, hitPt)
                 self.coaMarkerPos = np.getPos()
                 self.coaMarkerPos = np.getPos()
-                np.remove()
+                np.removeNode()
                 self.coaMarker.setPos(self.coaMarkerPos)
                 self.coaMarker.setPos(self.coaMarkerPos)
 
 
             iRay.collisionNodePath.removeNode()
             iRay.collisionNodePath.removeNode()

+ 3 - 3
direct/src/directtools/DirectManipulation.py

@@ -186,7 +186,7 @@ class DirectManipulationControl(DirectObject):
 
 
     def drawMarquee(self, startX, startY):
     def drawMarquee(self, startX, startY):
         if self.marquee:
         if self.marquee:
-            self.marquee.remove()
+            self.marquee.removeNode()
             self.marquee = None
             self.marquee = None
 
 
         if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
         if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
@@ -228,7 +228,7 @@ class DirectManipulationControl(DirectObject):
             skipFlags |= SKIP_CAMERA * (1 - base.getControl())
             skipFlags |= SKIP_CAMERA * (1 - base.getControl())
 
 
             if self.marquee:
             if self.marquee:
-                self.marquee.remove()
+                self.marquee.removeNode()
                 self.marquee = None
                 self.marquee = None
                 base.direct.deselectAll()
                 base.direct.deselectAll()
 
 
@@ -1691,7 +1691,7 @@ class ObjectHandles(NodePath, DirectObject):
         np.setPos(base.direct.camera, hitPt)
         np.setPos(base.direct.camera, hitPt)
         resultPt = Point3(0)
         resultPt = Point3(0)
         resultPt.assign(np.getPos())
         resultPt.assign(np.getPos())
-        np.remove()
+        np.removeNode()
         del iRay
         del iRay
         return resultPt
         return resultPt
 
 

+ 1 - 1
direct/src/directtools/DirectSession.py

@@ -900,7 +900,7 @@ class DirectSession(DirectObject):
             # If nothing specified, try selected node path
             # If nothing specified, try selected node path
             nodePath = self.selected.last
             nodePath = self.selected.last
         if nodePath:
         if nodePath:
-            nodePath.remove()
+            nodePath.removeNode()
 
 
     def removeAllSelected(self):
     def removeAllSelected(self):
         self.selected.removeAll()
         self.selected.removeAll()

+ 1 - 5
direct/src/distributed/DistributedObjectGlobalUD.py

@@ -26,11 +26,7 @@ class DistributedObjectGlobalUD(DistributedObjectUD):
 
 
     def execCommand(self, command, mwMgrId, avId, zoneId):
     def execCommand(self, command, mwMgrId, avId, zoneId):
         text = str(self.__execMessage(command))[:config.GetInt("ai-debug-length",300)]
         text = str(self.__execMessage(command))[:config.GetInt("ai-debug-length",300)]
-
-        dclass = uber.air.dclassesByName.get("PiratesMagicWordManagerAI")
-        dg = dclass.aiFormatUpdate(
-            "setMagicWordResponse", mwMgrId, (1<<32)+avId, uber.air.ourChannel, [text])
-        uber.air.send(dg)
+        self.notify.info(text)
 
 
     def __execMessage(self, message):
     def __execMessage(self, message):
         if not self.ExecNamespace:
         if not self.ExecNamespace:

+ 3 - 3
direct/src/distributed/cConnectionRepository.cxx

@@ -403,7 +403,7 @@ send_datagram(const Datagram &dg) {
 
 
 #ifdef WANT_NATIVE_NET
 #ifdef WANT_NATIVE_NET
   if (_native) {
   if (_native) {
-    bool result = _bdc.SendMessage();
+    bool result = _bdc.SendMessage(dg);
     if (!result && _bdc.IsConnected()) {
     if (!result && _bdc.IsConnected()) {
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
       ostringstream s;
       ostringstream s;
@@ -415,8 +415,8 @@ send_datagram(const Datagram &dg) {
 #endif
 #endif
 
 
       s << endl << "Error sending message: " << endl;
       s << endl << "Error sending message: " << endl;
-      msg.dump_hex(s);
-      s << "Message data: " << msg.get_data() << endl;
+      dg.dump_hex(s);
+      s << "Message data: " << dg.get_data() << endl;
 
 
       string message = s.str();
       string message = s.str();
       PyErr_SetString(exc_type, message.c_str());
       PyErr_SetString(exc_type, message.c_str());

+ 0 - 1
direct/src/extensions_native/.gitignore

@@ -1 +0,0 @@
-/extensions_darwin.py

+ 0 - 2
direct/src/gui/.gitignore

@@ -1,2 +0,0 @@
-/NL*
-/Nested*

+ 3 - 3
direct/src/gui/DirectScrolledList.py

@@ -20,7 +20,7 @@ class DirectScrolledListItem(DirectButton):
 
 
     def __init__(self, parent=None, **kw):
     def __init__(self, parent=None, **kw):
         assert self.notify.debugStateCall(self)
         assert self.notify.debugStateCall(self)
-        self.parent = parent
+        self._parent = parent
         if "command" in kw:
         if "command" in kw:
             self.nextCommand = kw.get("command")
             self.nextCommand = kw.get("command")
             del kw["command"]
             del kw["command"]
@@ -28,7 +28,7 @@ class DirectScrolledListItem(DirectButton):
             self.nextCommandExtraArgs = kw.get("extraArgs")
             self.nextCommandExtraArgs = kw.get("extraArgs")
             del kw["extraArgs"]
             del kw["extraArgs"]
         optiondefs = (
         optiondefs = (
-            ('parent', self.parent,    None),
+            ('parent', self._parent,    None),
             ('command', self.select, None),
             ('command', self.select, None),
             )
             )
         # Merge keyword options with default options
         # Merge keyword options with default options
@@ -39,7 +39,7 @@ class DirectScrolledListItem(DirectButton):
     def select(self):
     def select(self):
         assert self.notify.debugStateCall(self)
         assert self.notify.debugStateCall(self)
         self.nextCommand(*self.nextCommandExtraArgs)
         self.nextCommand(*self.nextCommandExtraArgs)
-        self.parent.selectListItem(self)
+        self._parent.selectListItem(self)
 
 
 
 
 class DirectScrolledList(DirectFrame):
 class DirectScrolledList(DirectFrame):

+ 0 - 8
direct/src/p3d/.gitignore

@@ -1,8 +0,0 @@
-/_vfsimporter.exp
-/_vfsimporter.lib
-/_vfsimporter.pyd
-/_vfsimporter.pyd.manifest
-/packp3d
-/ppackage
-/ppatcher
-/vc90.pdb

+ 11 - 1
direct/src/p3d/Packager.py

@@ -1848,7 +1848,7 @@ class Packager:
 
 
         def addEggFile(self, file):
         def addEggFile(self, file):
             # Precompile egg files to bam's.
             # Precompile egg files to bam's.
-            np = self.packager.loader.loadModel(file.filename)
+            np = self.packager.loader.loadModel(file.filename, self.packager.loaderOptions)
             if not np:
             if not np:
                 raise Exception('Could not read egg file %s' % (file.filename))
                 raise Exception('Could not read egg file %s' % (file.filename))
 
 
@@ -1862,6 +1862,8 @@ class Packager:
             if not bamFile.openRead(file.filename):
             if not bamFile.openRead(file.filename):
                 raise Exception('Could not read bam file %s' % (file.filename))
                 raise Exception('Could not read bam file %s' % (file.filename))
 
 
+            bamFile.getReader().setLoaderOptions(self.packager.loaderOptions)
+
             if not bamFile.resolve():
             if not bamFile.resolve():
                 raise Exception('Could not resolve bam file %s' % (file.filename))
                 raise Exception('Could not resolve bam file %s' % (file.filename))
 
 
@@ -2492,6 +2494,14 @@ class Packager:
         self.sfxManagerList = None
         self.sfxManagerList = None
         self.musicManager = None
         self.musicManager = None
 
 
+        # These options will be used when loading models and textures.  By
+        # default we don't load textures beyond the header and don't store
+        # models in the RAM cache in order to conserve on memory usage.
+        opts = LoaderOptions()
+        opts.setFlags(opts.getFlags() | LoaderOptions.LFNoRamCache)
+        opts.setTextureFlags(opts.getTextureFlags() & ~LoaderOptions.TFPreload)
+        self.loaderOptions = opts
+
         # This is filled in during readPackageDef().
         # This is filled in during readPackageDef().
         self.packageList = []
         self.packageList = []
 
 

+ 7 - 0
direct/src/p3d/panda3d.pdef

@@ -56,6 +56,9 @@ class panda3d(package):
            'direct.stdpy.*',
            'direct.stdpy.*',
            'direct.task.*')
            'direct.task.*')
 
 
+    # Keep these modules for backward compatibility.
+    module('pandac.PandaModules', 'pandac.extension_native_helpers')
+
     module('panda3d.core',
     module('panda3d.core',
            'panda3d.direct',
            'panda3d.direct',
            'panda3d.fx',
            'panda3d.fx',
@@ -462,6 +465,8 @@ class packp3d(p3d):
 
 
     mainModule('direct.p3d.packp3d')
     mainModule('direct.p3d.packp3d')
 
 
+    file('packp3d.prc', extract = True, text = "preload-textures false")
+
 
 
 class ppackage(p3d):
 class ppackage(p3d):
     # As above, a packaging utility.  This is the fully-general ppackage
     # As above, a packaging utility.  This is the fully-general ppackage
@@ -475,6 +480,8 @@ class ppackage(p3d):
 
 
     mainModule('direct.p3d.ppackage')
     mainModule('direct.p3d.ppackage')
 
 
+    file('ppackage.prc', extract = True, text = "preload-textures false")
+
 
 
 class ppatcher(p3d):
 class ppatcher(p3d):
     # A handy utility to go along with ppackage.  This builds
     # A handy utility to go along with ppackage.  This builds

+ 0 - 1
direct/src/plugin/.gitignore

@@ -1 +0,0 @@
-/p3d_plugin_config.h

+ 4 - 4
direct/src/plugin/p3dInstance.cxx

@@ -3450,8 +3450,8 @@ paint_window_osx_port() {
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
   size_t rowsize = _swbuffer->get_row_size();
   size_t rowsize = _swbuffer->get_row_size();
 
 
-  Rect src_rect = {0, 0, y_size, x_size};
-  Rect ddrc_rect = {0, 0, y_size, x_size};
+  Rect src_rect = {0, 0, (short)y_size, (short)x_size};
+  Rect ddrc_rect = {0, 0, (short)y_size, (short)x_size};
 
 
   QDErr err;
   QDErr err;
 
 
@@ -3502,7 +3502,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
 
 
   if (_buffer_image != NULL) {
   if (_buffer_image != NULL) {
-    CGRect region = { { 0, 0 }, { x_size, y_size } };
+    CGRect region = { { 0, 0 }, { (CGFloat)x_size, (CGFloat)y_size } };
     CGContextDrawImage(context, region, _buffer_image);
     CGContextDrawImage(context, region, _buffer_image);
   }
   }
 }
 }
@@ -3538,7 +3538,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
     // First, convert the coordinates from screen coordinates to browser
     // First, convert the coordinates from screen coordinates to browser
     // window coordinates.
     // window coordinates.
     WindowRef window = handle._handle._osx_cgcontext._window;
     WindowRef window = handle._handle._osx_cgcontext._window;
-    CGPoint cgpt = { pt.h, pt.v };
+    CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v };
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
                    kHICoordSpaceWindow, window);
                    kHICoordSpaceWindow, window);
 
 

+ 11 - 0
direct/src/plugin/p3dInstanceManager.cxx

@@ -1421,6 +1421,17 @@ create_runtime_environment() {
     }
     }
   }
   }
 
 
+#ifndef _WIN32
+  // If we're running from the console, make sure that terminating the parent
+  // process will cause the child process to terminate as well.
+  if (_console_environment) {
+    struct sigaction ignore;
+    memset(&ignore, 0, sizeof(ignore));
+    ignore.sa_handler = SIG_IGN;
+    sigaction(SIGINT, &ignore, NULL);
+  }
+#endif
+
   _created_runtime_environment = true;
   _created_runtime_environment = true;
 }
 }
 
 

+ 8 - 8
direct/src/plugin/p3dOsxSplashWindow.cxx

@@ -267,7 +267,7 @@ refresh() {
     return;
     return;
   }
   }
   if (_toplevel_window != NULL) {
   if (_toplevel_window != NULL) {
-    Rect r = { 0, 0, _win_height, _win_width };
+    Rect r = { 0, 0, (short)_win_height, (short)_win_width };
     InvalWindowRect(_toplevel_window, &r);
     InvalWindowRect(_toplevel_window, &r);
 
 
   } else {
   } else {
@@ -345,7 +345,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
   CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
   CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
   CGColorRef bg = CGColorCreate(rgb_space, bg_components);
   CGColorRef bg = CGColorCreate(rgb_space, bg_components);
 
 
-  CGRect region = { { 0, 0 }, { _win_width, _win_height } };
+  CGRect region = { { 0, 0 }, { (CGFloat)_win_width, (CGFloat)_win_height } };
   CGContextSetFillColorWithColor(context, bg);
   CGContextSetFillColorWithColor(context, bg);
   CGContextFillRect(context, region);
   CGContextFillRect(context, region);
 
 
@@ -407,7 +407,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
     // First, convert the coordinates from screen coordinates to browser
     // First, convert the coordinates from screen coordinates to browser
     // window coordinates.
     // window coordinates.
     WindowRef window = handle._handle._osx_cgcontext._window;
     WindowRef window = handle._handle._osx_cgcontext._window;
-    CGPoint cgpt = { pt.h, pt.v };
+    CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v };
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
                    kHICoordSpaceWindow, window);
                    kHICoordSpaceWindow, window);
 
 
@@ -617,7 +617,7 @@ paint_progress_bar(CGContextRef context) {
   int bar_x, bar_y, bar_width, bar_height;
   int bar_x, bar_y, bar_width, bar_height;
   get_bar_placement(bar_x, bar_y, bar_width, bar_height);
   get_bar_placement(bar_x, bar_y, bar_width, bar_height);
 
 
-  CGRect bar_rect = { { bar_x, bar_y }, { bar_width, bar_height } };
+  CGRect bar_rect = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)bar_width, (CGFloat)bar_height } };
 
 
   // Clear the entire progress bar to white (or the background color).
   // Clear the entire progress bar to white (or the background color).
   CGContextSetFillColorWithColor(context, bar_bg);
   CGContextSetFillColorWithColor(context, bar_bg);
@@ -627,7 +627,7 @@ paint_progress_bar(CGContextRef context) {
   if (_progress_known) {
   if (_progress_known) {
     int progress_width = (int)(bar_width * _install_progress + 0.5);
     int progress_width = (int)(bar_width * _install_progress + 0.5);
     if (progress_width != 0) {
     if (progress_width != 0) {
-      CGRect prog = { { bar_x, bar_y }, { progress_width, bar_height } };
+      CGRect prog = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)progress_width, (CGFloat)bar_height } };
       CGContextSetFillColorWithColor(context, bar);
       CGContextSetFillColorWithColor(context, bar);
       CGContextFillRect(context, prog);
       CGContextFillRect(context, prog);
     }
     }
@@ -642,7 +642,7 @@ paint_progress_bar(CGContextRef context) {
       progress = block_travel * 2 - progress;
       progress = block_travel * 2 - progress;
     }
     }
 
 
-    CGRect prog = { { bar_x + progress, bar_y }, { block_width, bar_height } };
+    CGRect prog = { { (CGFloat)(bar_x + progress), (CGFloat)bar_y }, { (CGFloat)block_width, (CGFloat)bar_height } };
     CGContextSetFillColorWithColor(context, bar);
     CGContextSetFillColorWithColor(context, bar);
     CGContextFillRect(context, prog);
     CGContextFillRect(context, prog);
   }
   }
@@ -652,8 +652,8 @@ paint_progress_bar(CGContextRef context) {
     // We offset the border by half a pixel, so we'll be drawing the one-pixel
     // We offset the border by half a pixel, so we'll be drawing the one-pixel
     // line through the middle of a pixel, and it won't try to antialias
     // line through the middle of a pixel, and it won't try to antialias
     // itself into a half-black two-pixel line.
     // itself into a half-black two-pixel line.
-    CGRect border_rect = { { bar_x - 0.5, bar_y - 0.5 },
-                           { bar_width + 1, bar_height + 1 } };
+    CGRect border_rect = { { (CGFloat)(bar_x - 0.5), (CGFloat)(bar_y - 0.5) },
+                           { (CGFloat)(bar_width + 1), (CGFloat)(bar_height + 1) } };
 
 
     CGContextBeginPath(context);
     CGContextBeginPath(context);
     CGContextSetLineWidth(context, 1);
     CGContextSetLineWidth(context, 1);

+ 0 - 1
direct/src/plugin_activex/.gitignore

@@ -1 +0,0 @@
-/P3DActiveX.rc

+ 0 - 1
direct/src/plugin_npapi/.gitignore

@@ -1 +0,0 @@
-/nppanda3d.rc

+ 0 - 2
direct/src/plugin_standalone/.gitignore

@@ -1,2 +0,0 @@
-/p3d_plugin_config.h
-/panda3d.rc

+ 12 - 3
direct/src/showbase/BufferViewer.py

@@ -278,6 +278,15 @@ class BufferViewer(DirectObject):
         self.analyzeTextureSet(self.exclude, exclude)
         self.analyzeTextureSet(self.exclude, exclude)
         self.analyzeTextureSet(self.include, include)
         self.analyzeTextureSet(self.include, include)
 
 
+        # Use a custom sampler when applying the textures.  This fixes
+        # wrap issues and prevents depth compare on shadow maps.
+        sampler = SamplerState()
+        sampler.setWrapU(SamplerState.WM_clamp)
+        sampler.setWrapV(SamplerState.WM_clamp)
+        sampler.setWrapW(SamplerState.WM_clamp)
+        sampler.setMinfilter(SamplerState.FT_linear)
+        sampler.setMagfilter(SamplerState.FT_nearest)
+
         # Generate a list of cards and the corresponding windows.
         # Generate a list of cards and the corresponding windows.
         cards = []
         cards = []
         wins = []
         wins = []
@@ -290,7 +299,7 @@ class BufferViewer(DirectObject):
                         for face in range(6):
                         for face in range(6):
                             self.cardmaker.setUvRangeCube(face)
                             self.cardmaker.setUvRangeCube(face)
                             card = NodePath(self.cardmaker.generate())
                             card = NodePath(self.cardmaker.generate())
-                            card.setTexture(tex)
+                            card.setTexture(tex, sampler)
                             cards.append(card)
                             cards.append(card)
                     elif (tex.getTextureType() == Texture.TT2dTextureArray):
                     elif (tex.getTextureType() == Texture.TT2dTextureArray):
                         for layer in range(tex.getZSize()):
                         for layer in range(tex.getZSize()):
@@ -301,11 +310,11 @@ class BufferViewer(DirectObject):
                             # the fixed-function pipeline, so we need to
                             # the fixed-function pipeline, so we need to
                             # enable the shader generator to view them.
                             # enable the shader generator to view them.
                             card.setShaderAuto()
                             card.setShaderAuto()
-                            card.setTexture(tex)
+                            card.setTexture(tex, sampler)
                             cards.append(card)
                             cards.append(card)
                     else:
                     else:
                         card = win.getTextureCard()
                         card = win.getTextureCard()
-                        card.setTexture(tex)
+                        card.setTexture(tex, sampler)
                         cards.append(card)
                         cards.append(card)
                     wins.append(win)
                     wins.append(win)
                     exclude[tex] = 1
                     exclude[tex] = 1

+ 59 - 3
direct/src/showbase/Loader.py

@@ -687,6 +687,63 @@ class Loader(DirectObject):
 
 
         return texture
         return texture
 
 
+    def load2DTextureArray(self, texturePattern, readMipmaps = False, okMissing = False,
+                      minfilter = None, magfilter = None, anisotropicDegree = None,
+                      loaderOptions = None, multiview = None, numViews = 2):
+        """
+        texturePattern is a string that contains a sequence of one or
+        more hash characters ('#'), which will be filled in with the
+        z-height number.  Returns a 2-D Texture array object, suitable
+        for rendering array of textures.
+
+        okMissing should be True to indicate the method should return
+        None if the texture file is not found.  If it is False, the
+        method will raise an exception if the texture file is not
+        found or cannot be loaded.
+
+        If readMipmaps is True, then the filename string must contain
+        two sequences of hash characters; the first group is filled in
+        with the z-height number, and the second group with the mipmap
+        index number.
+
+        If multiview is true, it indicates to load a multiview or
+        stereo texture.  In this case, numViews should also be
+        specified (the default is 2), and the sequence of texture
+        images will be divided into numViews views.  The total
+        z-height will be (numImages / numViews).  For instance, if you
+        read 16 images with numViews = 2, then you have created a
+        stereo multiview image, with z = 8.  In this example, images
+        numbered 0 - 7 will be part of the left eye view, and images
+        numbered 8 - 15 will be part of the right eye view.
+        """
+        assert Loader.notify.debug("Loading 2-D texture array: %s" % (texturePattern))
+        if loaderOptions is None:
+            loaderOptions = LoaderOptions()
+        else:
+            loaderOptions = LoaderOptions(loaderOptions)
+        if multiview is not None:
+            flags = loaderOptions.getTextureFlags()
+            if multiview:
+                flags |= LoaderOptions.TFMultiview
+            else:
+                flags &= ~LoaderOptions.TFMultiview
+            loaderOptions.setTextureFlags(flags)
+            loaderOptions.setTextureNumViews(numViews)
+
+        texture = TexturePool.load2dTextureArray(texturePattern, readMipmaps, loaderOptions)
+        if not texture and not okMissing:
+            message = 'Could not load 2-D texture array: %s' % (texturePattern)
+            raise IOError(message)
+
+        if minfilter is not None:
+            texture.setMinfilter(minfilter)
+        if magfilter is not None:
+            texture.setMagfilter(magfilter)
+        if anisotropicDegree is not None:
+            texture.setAnisotropicDegree(anisotropicDegree)
+
+        return texture
+
     def loadCubeMap(self, texturePattern, readMipmaps = False, okMissing = False,
     def loadCubeMap(self, texturePattern, readMipmaps = False, okMissing = False,
                     minfilter = None, magfilter = None, anisotropicDegree = None,
                     minfilter = None, magfilter = None, anisotropicDegree = None,
                     loaderOptions = None, multiview = None):
                     loaderOptions = None, multiview = None):
@@ -892,9 +949,8 @@ class Loader(DirectObject):
         for model in modelList:
         for model in modelList:
             request = ModelFlattenRequest(model.node())
             request = ModelFlattenRequest(model.node())
             request.setDoneEvent(self.hook)
             request.setDoneEvent(self.hook)
-            request.setPythonObject((cb, i))
             self.loader.loadAsync(request)
             self.loader.loadAsync(request)
-            cb.requests[request] = True
+            cb.requests.add(request)
             self.__requests[request] = (cb, i)
             self.__requests[request] = (cb, i)
             i += 1
             i += 1
         return cb
         return cb
@@ -910,7 +966,7 @@ class Loader(DirectObject):
             orig = origModelList[i].node()
             orig = origModelList[i].node()
             flat = models[i].node()
             flat = models[i].node()
             orig.copyAllProperties(flat)
             orig.copyAllProperties(flat)
-            orig.replaceNode(flat)
+            flat.replaceNode(orig)
 
 
         if callback:
         if callback:
             if gotList:
             if gotList:

+ 36 - 1
direct/src/showbase/PythonUtil.py

@@ -38,7 +38,6 @@ import os
 import sys
 import sys
 import random
 import random
 import time
 import time
-import importlib
 
 
 __report_indent = 3
 __report_indent = 3
 
 
@@ -61,6 +60,42 @@ def Functor(function, *args, **kArgs):
     return functor
     return functor
 """
 """
 
 
+try:
+    import importlib
+except ImportError:
+    # Backward compatibility for Python 2.6.
+    def _resolve_name(name, package, level):
+        if not hasattr(package, 'rindex'):
+            raise ValueError("'package' not set to a string")
+        dot = len(package)
+        for x in xrange(level, 1, -1):
+            try:
+                dot = package.rindex('.', 0, dot)
+            except ValueError:
+                raise ValueError("attempted relative import beyond top-level "
+                                  "package")
+        return "%s.%s" % (package[:dot], name)
+
+    def import_module(name, package=None):
+        if name.startswith('.'):
+            if not package:
+                raise TypeError("relative imports require the 'package' argument")
+            level = 0
+            for character in name:
+                if character != '.':
+                    break
+                level += 1
+            name = _resolve_name(name[level:], package, level)
+        __import__(name)
+        return sys.modules[name]
+
+    imp = import_module('imp')
+    importlib = imp.new_module("importlib")
+    importlib._resolve_name = _resolve_name
+    importlib.import_module = import_module
+    sys.modules['importlib'] = importlib
+
+
 class Functor:
 class Functor:
     def __init__(self, function, *args, **kargs):
     def __init__(self, function, *args, **kargs):
         assert callable(function), "function should be a callable obj"
         assert callable(function), "function should be a callable obj"

+ 0 - 4
direct/src/showbase/ShowBase.py

@@ -127,10 +127,6 @@ class ShowBase(DirectObject.DirectObject):
         ## just before Python is about to shut down.
         ## just before Python is about to shut down.
         self.finalExitCallbacks = []
         self.finalExitCallbacks = []
 
 
-        Task.TaskManager.taskTimerVerbose = self.config.GetBool('task-timer-verbose', 0)
-        Task.TaskManager.extendedExceptions = self.config.GetBool('extended-exceptions', 0)
-        Task.TaskManager.pStatsTasks = self.config.GetBool('pstats-tasks', 0)
-
         # Set up the TaskManager to reset the PStats clock back
         # Set up the TaskManager to reset the PStats clock back
         # whenever we resume from a pause.  This callback function is
         # whenever we resume from a pause.  This callback function is
         # a little hacky, but we can't call it directly from within
         # a little hacky, but we can't call it directly from within

+ 0 - 1
direct/src/showutil/.gitignore

@@ -1 +0,0 @@
-/runp3d

+ 4 - 1
direct/src/task/Task.py

@@ -102,7 +102,10 @@ Task.DtoolClassDict['loop'] = staticmethod(loop)
 class TaskManager:
 class TaskManager:
     notify = directNotify.newCategory("TaskManager")
     notify = directNotify.newCategory("TaskManager")
 
 
-    extendedExceptions = False
+    taskTimerVerbose = ConfigVariableBool('task-timer-verbose', False)
+    extendedExceptions = ConfigVariableBool('extended-exceptions', False)
+    pStatsTasks = ConfigVariableBool('pstats-tasks', False)
+
     MaxEpochSpeed = 1.0/30.0
     MaxEpochSpeed = 1.0/30.0
 
 
     def __init__(self):
     def __init__(self):

+ 2 - 2
direct/src/tkpanels/DirectSessionPanel.py

@@ -177,8 +177,8 @@ class DirectSessionPanel(AppShell):
             sgeFrame, nodePath = render,
             sgeFrame, nodePath = render,
             scrolledCanvas_hull_width = 250,
             scrolledCanvas_hull_width = 250,
             scrolledCanvas_hull_height = 300)
             scrolledCanvas_hull_height = 300)
-        self.SGE.pack(fill = BOTH, expand = 0)
-        sgeFrame.pack(side = LEFT, fill = 'both', expand = 0)
+        self.SGE.pack(fill = BOTH, expand = 1)
+        sgeFrame.pack(side = LEFT, fill = 'both', expand = 1)
 
 
         # Create the notebook pages
         # Create the notebook pages
         notebook = Pmw.NoteBook(notebookFrame)
         notebook = Pmw.NoteBook(notebookFrame)

+ 1 - 1
direct/src/tkwidgets/MemoryExplorer.py

@@ -284,7 +284,7 @@ class MemoryExplorerItem:
     def getNumChildren(self):
     def getNumChildren(self):
         return len(self.children)
         return len(self.children)
 
 
-    def getChildrenAsList(self):
+    def getChildren(self):
         return self.children
         return self.children
 
 
     def getName(self):
     def getName(self):

+ 0 - 7
dmodels/.gitignore

@@ -1,7 +0,0 @@
-*.egg
-*.pt
-/built/
-Makefile
-bams/
-optchar/
-pal_egg/

+ 0 - 6
dmodels/src/.gitignore

@@ -1,6 +0,0 @@
-/*.buildings
-/game_options.txt
-/prefixstrip
-/retarget/
-/textures.boo
-/topstrip/

+ 29 - 1
doc/ReleaseNotes

@@ -2,10 +2,12 @@
 
 
 This issue fixes several bugs that were still found in 1.9.2.
 This issue fixes several bugs that were still found in 1.9.2.
 
 
+* Fix crash when using homebrew Python on Mac OS X
 * Fix crash when running in Steam on Linux when using OpenAL
 * Fix crash when running in Steam on Linux when using OpenAL
 * Fix crash using wx/tkinter on Mac as long as want-wx/tk is set
 * Fix crash using wx/tkinter on Mac as long as want-wx/tk is set
 * Fix loading models from 'models' package with models/ prefix
 * Fix loading models from 'models' package with models/ prefix
 * Fix random crashes in task system
 * Fix random crashes in task system
+* Fix various race conditions causing threading issues
 * Fix memory leaks in BulletTriangleMesh
 * Fix memory leaks in BulletTriangleMesh
 * Fix loading old models with MovingPart<LMatrix4f>
 * Fix loading old models with MovingPart<LMatrix4f>
 * Improve performance of CPU vertex animation somewhat
 * Improve performance of CPU vertex animation somewhat
@@ -26,7 +28,33 @@ This issue fixes several bugs that were still found in 1.9.2.
 * Fix issues with certain Cg shader inputs in DX9
 * Fix issues with certain Cg shader inputs in DX9
 * Support uint8 index buffers in DX9
 * Support uint8 index buffers in DX9
 * Fix occasional frame lag when loading a big model asynchronously
 * Fix occasional frame lag when loading a big model asynchronously
-* Fix race condition reading string config var
+* Fix interrogate parsing issue with "const static"
+* Add back missing libp3pystub.a to Mac OS X SDK
+* Fix RAM caching of 2D texture arrays
+* Fix Ctrl+C interrupt propagation to runtime applications
+* Support for InvSphere, Box and Tube solids in bam2egg
+* Preserve "intangible" and "level" collide flags in bam2egg
+* Add normalized() method to vectors
+* asyncFlattenStrong with inPlace=True caused node to disappear
+* Fix asyncFlattenStrong called on nodes without parent
+* Fix is_playing() check when playing an animation backwards
+* Windows installer no longer clears %PATH% if longer than 1024 chars
+* Fix inoperative -tbn/-tbnall/-tbnauto options in egg-optchar
+* Fix tinydisplay texture errors on shutdown
+* Fix mipmap filtering issues in tinydisplay renderer
+* Fix exception when creating intervals before ShowBase is started
+* Fix rare X11 .ico cursor bug; also now supports PNG-compressed icons
+* Add keyword argument support to make() methods such as Shader.make()
+* Fix compilation errors with Bullet 2.84
+* Fix exception when trying to pickle NodePathCollection objects
+* Fix error when trying to raise vectors to a power
+* GLSL: fix error when legacy matrix generator inputs are mat3
+* Now tries to preserve refresh rate when switching fullscreen on Windows
+* Fix back-to-front sorting when gl-coordinate-system is changed
+* Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1)
+* get_keyboard_map now includes keys on layouts with special characters
+* Fix crash due to incorrect alignment when compiling Eigen with AVX
+* Fix crash when writing 16-bit .tif file (now silently downsamples)
 
 
 ------------------------  RELEASE 1.9.2  ------------------------
 ------------------------  RELEASE 1.9.2  ------------------------
 
 

+ 0 - 7
dtool/.gitignore

@@ -1,7 +0,0 @@
-/dtool_config.h
-# These are files that are generated within the source tree by the
-# ppremake system.
-Makefile
-pp.dep
-/built/
-Opt?-*

+ 0 - 2
dtool/src/cppparser/.gitignore

@@ -1,2 +0,0 @@
-/cppBison.cxx
-/cppBison.h

+ 10 - 1
dtool/src/cppparser/cppArrayType.cxx

@@ -13,6 +13,7 @@
 
 
 #include "cppArrayType.h"
 #include "cppArrayType.h"
 #include "cppExpression.h"
 #include "cppExpression.h"
+#include "cppPointerType.h"
 
 
 /**
 /**
  *
  *
@@ -63,6 +64,14 @@ is_tbd() const {
   return _element_type->is_tbd();
   return _element_type->is_tbd();
 }
 }
 
 
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPArrayType::
+is_standard_layout() const {
+  return _element_type->is_standard_layout();
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -76,7 +85,7 @@ is_trivial() const {
  */
  */
 bool CPPArrayType::
 bool CPPArrayType::
 is_default_constructible() const {
 is_default_constructible() const {
-  return _element_type->is_default_constructible();
+  return _bounds != NULL && _element_type->is_default_constructible();
 }
 }
 
 
 /**
 /**

+ 1 - 0
dtool/src/cppparser/cppArrayType.h

@@ -38,6 +38,7 @@ public:
   virtual CPPType *resolve_type(CPPScope *current_scope,
   virtual CPPType *resolve_type(CPPScope *current_scope,
                                 CPPScope *global_scope);
                                 CPPScope *global_scope);
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 809 - 418
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 310 - 253
dtool/src/cppparser/cppBison.h.prebuilt

@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 2.7.  */
 
 
 /* Bison interface for Yacc-like parsers in C
 /* Bison interface for Yacc-like parsers in C
 
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
 
 
    This program is free software: you can redistribute it and/or modify
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
@@ -30,9 +30,9 @@
    This special exception was added by the Free Software Foundation in
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
    version 2.2 of Bison.  */
 
 
-#ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
-# define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
-/* Debug traces.  */
+#ifndef YY_CPPYY_BUILT_X64_TMP_CPPBISON_YXX_H_INCLUDED
+# define YY_CPPYY_BUILT_X64_TMP_CPPBISON_YXX_H_INCLUDED
+/* Enabling traces.  */
 #ifndef YYDEBUG
 #ifndef YYDEBUG
 # define YYDEBUG 0
 # define YYDEBUG 0
 #endif
 #endif
@@ -40,135 +40,156 @@
 extern int cppyydebug;
 extern int cppyydebug;
 #endif
 #endif
 
 
-/* Token type.  */
+/* Tokens.  */
 #ifndef YYTOKENTYPE
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
 # define YYTOKENTYPE
-  enum yytokentype
-  {
-    REAL = 258,
-    INTEGER = 259,
-    CHAR_TOK = 260,
-    SIMPLE_STRING = 261,
-    SIMPLE_IDENTIFIER = 262,
-    STRING_LITERAL = 263,
-    CUSTOM_LITERAL = 264,
-    IDENTIFIER = 265,
-    TYPENAME_IDENTIFIER = 266,
-    SCOPING = 267,
-    TYPEDEFNAME = 268,
-    ELLIPSIS = 269,
-    OROR = 270,
-    ANDAND = 271,
-    EQCOMPARE = 272,
-    NECOMPARE = 273,
-    LECOMPARE = 274,
-    GECOMPARE = 275,
-    LSHIFT = 276,
-    RSHIFT = 277,
-    POINTSAT_STAR = 278,
-    DOT_STAR = 279,
-    UNARY = 280,
-    UNARY_NOT = 281,
-    UNARY_NEGATE = 282,
-    UNARY_MINUS = 283,
-    UNARY_PLUS = 284,
-    UNARY_STAR = 285,
-    UNARY_REF = 286,
-    POINTSAT = 287,
-    SCOPE = 288,
-    PLUSPLUS = 289,
-    MINUSMINUS = 290,
-    TIMESEQUAL = 291,
-    DIVIDEEQUAL = 292,
-    MODEQUAL = 293,
-    PLUSEQUAL = 294,
-    MINUSEQUAL = 295,
-    OREQUAL = 296,
-    ANDEQUAL = 297,
-    XOREQUAL = 298,
-    LSHIFTEQUAL = 299,
-    RSHIFTEQUAL = 300,
-    KW_ALIGNAS = 301,
-    KW_ALIGNOF = 302,
-    KW_AUTO = 303,
-    KW_BEGIN_PUBLISH = 304,
-    KW_BLOCKING = 305,
-    KW_BOOL = 306,
-    KW_CATCH = 307,
-    KW_CHAR = 308,
-    KW_CHAR16_T = 309,
-    KW_CHAR32_T = 310,
-    KW_CLASS = 311,
-    KW_CONST = 312,
-    KW_CONSTEXPR = 313,
-    KW_CONST_CAST = 314,
-    KW_DECLTYPE = 315,
-    KW_DEFAULT = 316,
-    KW_DELETE = 317,
-    KW_DOUBLE = 318,
-    KW_DYNAMIC_CAST = 319,
-    KW_ELSE = 320,
-    KW_END_PUBLISH = 321,
-    KW_ENUM = 322,
-    KW_EXTENSION = 323,
-    KW_EXTERN = 324,
-    KW_EXPLICIT = 325,
-    KW_PUBLISHED = 326,
-    KW_FALSE = 327,
-    KW_FINAL = 328,
-    KW_FLOAT = 329,
-    KW_FRIEND = 330,
-    KW_FOR = 331,
-    KW_GOTO = 332,
-    KW_IF = 333,
-    KW_INLINE = 334,
-    KW_INT = 335,
-    KW_LONG = 336,
-    KW_MAKE_MAP_PROPERTY = 337,
-    KW_MAKE_PROPERTY = 338,
-    KW_MAKE_PROPERTY2 = 339,
-    KW_MAKE_SEQ = 340,
-    KW_MAKE_SEQ_PROPERTY = 341,
-    KW_MUTABLE = 342,
-    KW_NAMESPACE = 343,
-    KW_NEW = 344,
-    KW_NOEXCEPT = 345,
-    KW_NULLPTR = 346,
-    KW_OPERATOR = 347,
-    KW_OVERRIDE = 348,
-    KW_PRIVATE = 349,
-    KW_PROTECTED = 350,
-    KW_PUBLIC = 351,
-    KW_REGISTER = 352,
-    KW_REINTERPRET_CAST = 353,
-    KW_RETURN = 354,
-    KW_SHORT = 355,
-    KW_SIGNED = 356,
-    KW_SIZEOF = 357,
-    KW_STATIC = 358,
-    KW_STATIC_ASSERT = 359,
-    KW_STATIC_CAST = 360,
-    KW_STRUCT = 361,
-    KW_TEMPLATE = 362,
-    KW_THREAD_LOCAL = 363,
-    KW_THROW = 364,
-    KW_TRUE = 365,
-    KW_TRY = 366,
-    KW_TYPEDEF = 367,
-    KW_TYPEID = 368,
-    KW_TYPENAME = 369,
-    KW_UNION = 370,
-    KW_UNSIGNED = 371,
-    KW_USING = 372,
-    KW_VIRTUAL = 373,
-    KW_VOID = 374,
-    KW_VOLATILE = 375,
-    KW_WCHAR_T = 376,
-    KW_WHILE = 377,
-    START_CPP = 378,
-    START_CONST_EXPR = 379,
-    START_TYPE = 380
-  };
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     REAL = 258,
+     INTEGER = 259,
+     CHAR_TOK = 260,
+     SIMPLE_STRING = 261,
+     SIMPLE_IDENTIFIER = 262,
+     STRING_LITERAL = 263,
+     CUSTOM_LITERAL = 264,
+     IDENTIFIER = 265,
+     TYPENAME_IDENTIFIER = 266,
+     TYPEPACK_IDENTIFIER = 267,
+     SCOPING = 268,
+     TYPEDEFNAME = 269,
+     ELLIPSIS = 270,
+     OROR = 271,
+     ANDAND = 272,
+     EQCOMPARE = 273,
+     NECOMPARE = 274,
+     LECOMPARE = 275,
+     GECOMPARE = 276,
+     LSHIFT = 277,
+     RSHIFT = 278,
+     POINTSAT_STAR = 279,
+     DOT_STAR = 280,
+     UNARY = 281,
+     UNARY_NOT = 282,
+     UNARY_NEGATE = 283,
+     UNARY_MINUS = 284,
+     UNARY_PLUS = 285,
+     UNARY_STAR = 286,
+     UNARY_REF = 287,
+     POINTSAT = 288,
+     SCOPE = 289,
+     PLUSPLUS = 290,
+     MINUSMINUS = 291,
+     TIMESEQUAL = 292,
+     DIVIDEEQUAL = 293,
+     MODEQUAL = 294,
+     PLUSEQUAL = 295,
+     MINUSEQUAL = 296,
+     OREQUAL = 297,
+     ANDEQUAL = 298,
+     XOREQUAL = 299,
+     LSHIFTEQUAL = 300,
+     RSHIFTEQUAL = 301,
+     ATTR_LEFT = 302,
+     ATTR_RIGHT = 303,
+     KW_ALIGNAS = 304,
+     KW_ALIGNOF = 305,
+     KW_AUTO = 306,
+     KW_BEGIN_PUBLISH = 307,
+     KW_BLOCKING = 308,
+     KW_BOOL = 309,
+     KW_CATCH = 310,
+     KW_CHAR = 311,
+     KW_CHAR16_T = 312,
+     KW_CHAR32_T = 313,
+     KW_CLASS = 314,
+     KW_CONST = 315,
+     KW_CONSTEXPR = 316,
+     KW_CONST_CAST = 317,
+     KW_DECLTYPE = 318,
+     KW_DEFAULT = 319,
+     KW_DELETE = 320,
+     KW_DOUBLE = 321,
+     KW_DYNAMIC_CAST = 322,
+     KW_ELSE = 323,
+     KW_END_PUBLISH = 324,
+     KW_ENUM = 325,
+     KW_EXTENSION = 326,
+     KW_EXTERN = 327,
+     KW_EXPLICIT = 328,
+     KW_PUBLISHED = 329,
+     KW_FALSE = 330,
+     KW_FINAL = 331,
+     KW_FLOAT = 332,
+     KW_FRIEND = 333,
+     KW_FOR = 334,
+     KW_GOTO = 335,
+     KW_HAS_VIRTUAL_DESTRUCTOR = 336,
+     KW_IF = 337,
+     KW_INLINE = 338,
+     KW_INT = 339,
+     KW_IS_ABSTRACT = 340,
+     KW_IS_BASE_OF = 341,
+     KW_IS_CLASS = 342,
+     KW_IS_CONSTRUCTIBLE = 343,
+     KW_IS_CONVERTIBLE_TO = 344,
+     KW_IS_DESTRUCTIBLE = 345,
+     KW_IS_EMPTY = 346,
+     KW_IS_ENUM = 347,
+     KW_IS_FINAL = 348,
+     KW_IS_FUNDAMENTAL = 349,
+     KW_IS_POD = 350,
+     KW_IS_POLYMORPHIC = 351,
+     KW_IS_STANDARD_LAYOUT = 352,
+     KW_IS_TRIVIAL = 353,
+     KW_IS_UNION = 354,
+     KW_LONG = 355,
+     KW_MAKE_MAP_PROPERTY = 356,
+     KW_MAKE_PROPERTY = 357,
+     KW_MAKE_PROPERTY2 = 358,
+     KW_MAKE_SEQ = 359,
+     KW_MAKE_SEQ_PROPERTY = 360,
+     KW_MUTABLE = 361,
+     KW_NAMESPACE = 362,
+     KW_NEW = 363,
+     KW_NOEXCEPT = 364,
+     KW_NULLPTR = 365,
+     KW_OPERATOR = 366,
+     KW_OVERRIDE = 367,
+     KW_PRIVATE = 368,
+     KW_PROTECTED = 369,
+     KW_PUBLIC = 370,
+     KW_REGISTER = 371,
+     KW_REINTERPRET_CAST = 372,
+     KW_RETURN = 373,
+     KW_SHORT = 374,
+     KW_SIGNED = 375,
+     KW_SIZEOF = 376,
+     KW_STATIC = 377,
+     KW_STATIC_ASSERT = 378,
+     KW_STATIC_CAST = 379,
+     KW_STRUCT = 380,
+     KW_TEMPLATE = 381,
+     KW_THREAD_LOCAL = 382,
+     KW_THROW = 383,
+     KW_TRUE = 384,
+     KW_TRY = 385,
+     KW_TYPEDEF = 386,
+     KW_TYPEID = 387,
+     KW_TYPENAME = 388,
+     KW_UNDERLYING_TYPE = 389,
+     KW_UNION = 390,
+     KW_UNSIGNED = 391,
+     KW_USING = 392,
+     KW_VIRTUAL = 393,
+     KW_VOID = 394,
+     KW_VOLATILE = 395,
+     KW_WCHAR_T = 396,
+     KW_WHILE = 397,
+     START_CPP = 398,
+     START_CONST_EXPR = 399,
+     START_TYPE = 400
+   };
 #endif
 #endif
 /* Tokens.  */
 /* Tokens.  */
 #define REAL 258
 #define REAL 258
@@ -180,139 +201,175 @@ extern int cppyydebug;
 #define CUSTOM_LITERAL 264
 #define CUSTOM_LITERAL 264
 #define IDENTIFIER 265
 #define IDENTIFIER 265
 #define TYPENAME_IDENTIFIER 266
 #define TYPENAME_IDENTIFIER 266
-#define SCOPING 267
-#define TYPEDEFNAME 268
-#define ELLIPSIS 269
-#define OROR 270
-#define ANDAND 271
-#define EQCOMPARE 272
-#define NECOMPARE 273
-#define LECOMPARE 274
-#define GECOMPARE 275
-#define LSHIFT 276
-#define RSHIFT 277
-#define POINTSAT_STAR 278
-#define DOT_STAR 279
-#define UNARY 280
-#define UNARY_NOT 281
-#define UNARY_NEGATE 282
-#define UNARY_MINUS 283
-#define UNARY_PLUS 284
-#define UNARY_STAR 285
-#define UNARY_REF 286
-#define POINTSAT 287
-#define SCOPE 288
-#define PLUSPLUS 289
-#define MINUSMINUS 290
-#define TIMESEQUAL 291
-#define DIVIDEEQUAL 292
-#define MODEQUAL 293
-#define PLUSEQUAL 294
-#define MINUSEQUAL 295
-#define OREQUAL 296
-#define ANDEQUAL 297
-#define XOREQUAL 298
-#define LSHIFTEQUAL 299
-#define RSHIFTEQUAL 300
-#define KW_ALIGNAS 301
-#define KW_ALIGNOF 302
-#define KW_AUTO 303
-#define KW_BEGIN_PUBLISH 304
-#define KW_BLOCKING 305
-#define KW_BOOL 306
-#define KW_CATCH 307
-#define KW_CHAR 308
-#define KW_CHAR16_T 309
-#define KW_CHAR32_T 310
-#define KW_CLASS 311
-#define KW_CONST 312
-#define KW_CONSTEXPR 313
-#define KW_CONST_CAST 314
-#define KW_DECLTYPE 315
-#define KW_DEFAULT 316
-#define KW_DELETE 317
-#define KW_DOUBLE 318
-#define KW_DYNAMIC_CAST 319
-#define KW_ELSE 320
-#define KW_END_PUBLISH 321
-#define KW_ENUM 322
-#define KW_EXTENSION 323
-#define KW_EXTERN 324
-#define KW_EXPLICIT 325
-#define KW_PUBLISHED 326
-#define KW_FALSE 327
-#define KW_FINAL 328
-#define KW_FLOAT 329
-#define KW_FRIEND 330
-#define KW_FOR 331
-#define KW_GOTO 332
-#define KW_IF 333
-#define KW_INLINE 334
-#define KW_INT 335
-#define KW_LONG 336
-#define KW_MAKE_MAP_PROPERTY 337
-#define KW_MAKE_PROPERTY 338
-#define KW_MAKE_PROPERTY2 339
-#define KW_MAKE_SEQ 340
-#define KW_MAKE_SEQ_PROPERTY 341
-#define KW_MUTABLE 342
-#define KW_NAMESPACE 343
-#define KW_NEW 344
-#define KW_NOEXCEPT 345
-#define KW_NULLPTR 346
-#define KW_OPERATOR 347
-#define KW_OVERRIDE 348
-#define KW_PRIVATE 349
-#define KW_PROTECTED 350
-#define KW_PUBLIC 351
-#define KW_REGISTER 352
-#define KW_REINTERPRET_CAST 353
-#define KW_RETURN 354
-#define KW_SHORT 355
-#define KW_SIGNED 356
-#define KW_SIZEOF 357
-#define KW_STATIC 358
-#define KW_STATIC_ASSERT 359
-#define KW_STATIC_CAST 360
-#define KW_STRUCT 361
-#define KW_TEMPLATE 362
-#define KW_THREAD_LOCAL 363
-#define KW_THROW 364
-#define KW_TRUE 365
-#define KW_TRY 366
-#define KW_TYPEDEF 367
-#define KW_TYPEID 368
-#define KW_TYPENAME 369
-#define KW_UNION 370
-#define KW_UNSIGNED 371
-#define KW_USING 372
-#define KW_VIRTUAL 373
-#define KW_VOID 374
-#define KW_VOLATILE 375
-#define KW_WCHAR_T 376
-#define KW_WHILE 377
-#define START_CPP 378
-#define START_CONST_EXPR 379
-#define START_TYPE 380
+#define TYPEPACK_IDENTIFIER 267
+#define SCOPING 268
+#define TYPEDEFNAME 269
+#define ELLIPSIS 270
+#define OROR 271
+#define ANDAND 272
+#define EQCOMPARE 273
+#define NECOMPARE 274
+#define LECOMPARE 275
+#define GECOMPARE 276
+#define LSHIFT 277
+#define RSHIFT 278
+#define POINTSAT_STAR 279
+#define DOT_STAR 280
+#define UNARY 281
+#define UNARY_NOT 282
+#define UNARY_NEGATE 283
+#define UNARY_MINUS 284
+#define UNARY_PLUS 285
+#define UNARY_STAR 286
+#define UNARY_REF 287
+#define POINTSAT 288
+#define SCOPE 289
+#define PLUSPLUS 290
+#define MINUSMINUS 291
+#define TIMESEQUAL 292
+#define DIVIDEEQUAL 293
+#define MODEQUAL 294
+#define PLUSEQUAL 295
+#define MINUSEQUAL 296
+#define OREQUAL 297
+#define ANDEQUAL 298
+#define XOREQUAL 299
+#define LSHIFTEQUAL 300
+#define RSHIFTEQUAL 301
+#define ATTR_LEFT 302
+#define ATTR_RIGHT 303
+#define KW_ALIGNAS 304
+#define KW_ALIGNOF 305
+#define KW_AUTO 306
+#define KW_BEGIN_PUBLISH 307
+#define KW_BLOCKING 308
+#define KW_BOOL 309
+#define KW_CATCH 310
+#define KW_CHAR 311
+#define KW_CHAR16_T 312
+#define KW_CHAR32_T 313
+#define KW_CLASS 314
+#define KW_CONST 315
+#define KW_CONSTEXPR 316
+#define KW_CONST_CAST 317
+#define KW_DECLTYPE 318
+#define KW_DEFAULT 319
+#define KW_DELETE 320
+#define KW_DOUBLE 321
+#define KW_DYNAMIC_CAST 322
+#define KW_ELSE 323
+#define KW_END_PUBLISH 324
+#define KW_ENUM 325
+#define KW_EXTENSION 326
+#define KW_EXTERN 327
+#define KW_EXPLICIT 328
+#define KW_PUBLISHED 329
+#define KW_FALSE 330
+#define KW_FINAL 331
+#define KW_FLOAT 332
+#define KW_FRIEND 333
+#define KW_FOR 334
+#define KW_GOTO 335
+#define KW_HAS_VIRTUAL_DESTRUCTOR 336
+#define KW_IF 337
+#define KW_INLINE 338
+#define KW_INT 339
+#define KW_IS_ABSTRACT 340
+#define KW_IS_BASE_OF 341
+#define KW_IS_CLASS 342
+#define KW_IS_CONSTRUCTIBLE 343
+#define KW_IS_CONVERTIBLE_TO 344
+#define KW_IS_DESTRUCTIBLE 345
+#define KW_IS_EMPTY 346
+#define KW_IS_ENUM 347
+#define KW_IS_FINAL 348
+#define KW_IS_FUNDAMENTAL 349
+#define KW_IS_POD 350
+#define KW_IS_POLYMORPHIC 351
+#define KW_IS_STANDARD_LAYOUT 352
+#define KW_IS_TRIVIAL 353
+#define KW_IS_UNION 354
+#define KW_LONG 355
+#define KW_MAKE_MAP_PROPERTY 356
+#define KW_MAKE_PROPERTY 357
+#define KW_MAKE_PROPERTY2 358
+#define KW_MAKE_SEQ 359
+#define KW_MAKE_SEQ_PROPERTY 360
+#define KW_MUTABLE 361
+#define KW_NAMESPACE 362
+#define KW_NEW 363
+#define KW_NOEXCEPT 364
+#define KW_NULLPTR 365
+#define KW_OPERATOR 366
+#define KW_OVERRIDE 367
+#define KW_PRIVATE 368
+#define KW_PROTECTED 369
+#define KW_PUBLIC 370
+#define KW_REGISTER 371
+#define KW_REINTERPRET_CAST 372
+#define KW_RETURN 373
+#define KW_SHORT 374
+#define KW_SIGNED 375
+#define KW_SIZEOF 376
+#define KW_STATIC 377
+#define KW_STATIC_ASSERT 378
+#define KW_STATIC_CAST 379
+#define KW_STRUCT 380
+#define KW_TEMPLATE 381
+#define KW_THREAD_LOCAL 382
+#define KW_THROW 383
+#define KW_TRUE 384
+#define KW_TRY 385
+#define KW_TYPEDEF 386
+#define KW_TYPEID 387
+#define KW_TYPENAME 388
+#define KW_UNDERLYING_TYPE 389
+#define KW_UNION 390
+#define KW_UNSIGNED 391
+#define KW_USING 392
+#define KW_VIRTUAL 393
+#define KW_VOID 394
+#define KW_VOLATILE 395
+#define KW_WCHAR_T 396
+#define KW_WHILE 397
+#define START_CPP 398
+#define START_CONST_EXPR 399
+#define START_TYPE 400
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 
 
-/* Value type.  */
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
 
 
-/* Location type.  */
 #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
 #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE YYLTYPE;
-struct YYLTYPE
+typedef struct YYLTYPE
 {
 {
   int first_line;
   int first_line;
   int first_column;
   int first_column;
   int last_line;
   int last_line;
   int last_column;
   int last_column;
-};
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
 # define YYLTYPE_IS_DECLARED 1
 # define YYLTYPE_IS_DECLARED 1
 # define YYLTYPE_IS_TRIVIAL 1
 # define YYLTYPE_IS_TRIVIAL 1
 #endif
 #endif
 
 
 
 
-
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int cppyyparse (void *YYPARSE_PARAM);
+#else
+int cppyyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
 int cppyyparse (void);
 int cppyyparse (void);
+#else
+int cppyyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
 
 
-#endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED  */
+#endif /* !YY_CPPYY_BUILT_X64_TMP_CPPBISON_YXX_H_INCLUDED  */

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 482 - 131
dtool/src/cppparser/cppBison.yxx


+ 4 - 0
dtool/src/cppparser/cppBisonDefs.h

@@ -23,6 +23,7 @@
 
 
 #include <string>
 #include <string>
 
 
+#include "cppClosureType.h"
 #include "cppExtensionType.h"
 #include "cppExtensionType.h"
 #include "cppFile.h"
 #include "cppFile.h"
 
 
@@ -42,6 +43,7 @@ class CPPParameterList;
 class CPPTemplateParameterList;
 class CPPTemplateParameterList;
 class CPPScope;
 class CPPScope;
 class CPPIdentifier;
 class CPPIdentifier;
+class CPPCaptureType;
 
 
 void parse_cpp(CPPParser *cp);
 void parse_cpp(CPPParser *cp);
 CPPExpression *parse_const_expr(CPPPreprocessor *pp,
 CPPExpression *parse_const_expr(CPPPreprocessor *pp,
@@ -81,6 +83,8 @@ public:
     CPPExtensionType::Type extension_enum;
     CPPExtensionType::Type extension_enum;
     CPPExpression *expr;
     CPPExpression *expr;
     CPPIdentifier *identifier;
     CPPIdentifier *identifier;
+    CPPClosureType *closure_type;
+    CPPClosureType::Capture *capture;
   } u;
   } u;
 };
 };
 #define YYSTYPE cppyystype
 #define YYSTYPE cppyystype

+ 26 - 3
dtool/src/cppparser/cppClassTemplateParameter.cxx

@@ -21,7 +21,8 @@ CPPClassTemplateParameter::
 CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) :
 CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) :
   CPPType(CPPFile()),
   CPPType(CPPFile()),
   _ident(ident),
   _ident(ident),
-  _default_type(default_type)
+  _default_type(default_type),
+  _packed(false)
 {
 {
 }
 }
 
 
@@ -41,8 +42,14 @@ is_fully_specified() const {
 void CPPClassTemplateParameter::
 void CPPClassTemplateParameter::
 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
   if (complete) {
   if (complete) {
-    out << "class ";
-    _ident->output(out, scope);
+    out << "class";
+    if (_packed) {
+      out << "...";
+    }
+    if (_ident != NULL) {
+      out << " ";
+      _ident->output(out, scope);
+    }
     if (_default_type) {
     if (_default_type) {
       out << " = ";
       out << " = ";
       _default_type->output(out, indent_level, scope, false);
       _default_type->output(out, indent_level, scope, false);
@@ -82,6 +89,14 @@ is_equal(const CPPDeclaration *other) const {
     return false;
     return false;
   }
   }
 
 
+  if (_packed != ot->_packed) {
+    return false;
+  }
+
+  if (_ident == NULL || ot->_ident == NULL) {
+    return _ident == ot->_ident;
+  }
+
   return *_ident == *ot->_ident;
   return *_ident == *ot->_ident;
 }
 }
 
 
@@ -99,5 +114,13 @@ is_less(const CPPDeclaration *other) const {
     return _default_type < ot->_default_type;
     return _default_type < ot->_default_type;
   }
   }
 
 
+  if (_packed != ot->_packed) {
+    return _packed < ot->_packed;
+  }
+
+  if (_ident == NULL || ot->_ident == NULL) {
+    return _ident < ot->_ident;
+  }
+
   return *_ident < *ot->_ident;
   return *_ident < *ot->_ident;
 }
 }

+ 1 - 0
dtool/src/cppparser/cppClassTemplateParameter.h

@@ -37,6 +37,7 @@ public:
 
 
   CPPIdentifier *_ident;
   CPPIdentifier *_ident;
   CPPType *_default_type;
   CPPType *_default_type;
+  bool _packed;
 
 
 protected:
 protected:
   virtual bool is_equal(const CPPDeclaration *other) const;
   virtual bool is_equal(const CPPDeclaration *other) const;

+ 195 - 0
dtool/src/cppparser/cppClosureType.cxx

@@ -0,0 +1,195 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file cppClosureType.cxx
+ * @author rdb
+ * @date 2017-01-14
+ */
+
+#include "cppClosureType.h"
+#include "cppExpression.h"
+
+/**
+ *
+ */
+CPPClosureType::
+CPPClosureType(CaptureType default_capture) :
+  CPPFunctionType(NULL, NULL, 0),
+  _default_capture(default_capture) {
+}
+
+/**
+ *
+ */
+CPPClosureType::
+CPPClosureType(const CPPClosureType &copy) :
+  CPPFunctionType(copy),
+  _captures(copy._captures),
+  _default_capture(copy._default_capture)
+{
+}
+
+/**
+ *
+ */
+void CPPClosureType::
+operator = (const CPPClosureType &copy) {
+  CPPFunctionType::operator = (copy);
+  _captures = copy._captures;
+  _default_capture = copy._default_capture;
+}
+
+/**
+ * Adds a new capture to the beginning of the capture list.
+ */
+void CPPClosureType::
+add_capture(string name, CaptureType type, CPPExpression *initializer) {
+  if (type == CT_none) {
+    if (name == "this") {
+      type = CT_by_reference;
+    } else {
+      type = CT_by_value;
+    }
+  }
+
+  Capture capture = {move(name), type, initializer};
+  _captures.insert(_captures.begin(), move(capture));
+}
+
+/**
+ * Returns true if this declaration is an actual, factual declaration, or
+ * false if some part of the declaration depends on a template parameter which
+ * has not yet been instantiated.
+ */
+bool CPPClosureType::
+is_fully_specified() const {
+  return CPPFunctionType::is_fully_specified();
+}
+
+/**
+ * Returns true if the type is default-constructible.
+ */
+bool CPPClosureType::
+is_default_constructible() const {
+  return false;
+}
+
+/**
+ * Returns true if the type is copy-constructible.
+ */
+bool CPPClosureType::
+is_copy_constructible() const {
+  return true;
+}
+
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPClosureType::
+is_destructible() const {
+  return true;
+}
+
+/**
+ *
+ */
+void CPPClosureType::
+output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  out.put('[');
+
+  bool have_capture = false;
+  switch (_default_capture) {
+  case CT_none:
+    break;
+  case CT_by_reference:
+    out.put('&');
+    have_capture = true;
+    break;
+  case CT_by_value:
+    out.put('=');
+    have_capture = true;
+    break;
+  }
+
+  Captures::const_iterator it;
+  for (it = _captures.begin(); it != _captures.end(); ++it) {
+    const Capture &capture = *it;
+    if (have_capture) {
+      out << ", ";
+    }
+    if (capture._name == "this") {
+      if (capture._type == CT_by_value) {
+        out.put('*');
+      }
+    } else {
+      if (capture._type == CT_by_reference) {
+        out.put('&');
+      }
+    }
+    out << capture._name;
+
+    if (capture._initializer != NULL) {
+      out << " = " << *capture._initializer;
+    }
+
+    have_capture = true;
+  }
+  out.put(']');
+
+  if (_parameters != NULL) {
+    out.put('(');
+    _parameters->output(out, scope, true, -1);
+    out.put(')');
+  }
+
+  if (_flags & F_noexcept) {
+    out << " noexcept";
+  }
+
+  if (_return_type != NULL) {
+    out << " -> ";
+    _return_type->output(out, indent_level, scope, false);
+  }
+
+  out << " {}";
+}
+
+/**
+ *
+ */
+CPPDeclaration::SubType CPPClosureType::
+get_subtype() const {
+  return ST_closure;
+}
+
+/**
+ *
+ */
+CPPClosureType *CPPClosureType::
+as_closure_type() {
+  return this;
+}
+
+/**
+ * Called by CPPDeclaration() to determine whether this type is equivalent to
+ * another type of the same type.
+ */
+bool CPPClosureType::
+is_equal(const CPPDeclaration *other) const {
+  return (this == other);
+}
+
+
+/**
+ * Called by CPPDeclaration() to determine whether this type should be ordered
+ * before another type of the same type, in an arbitrary but fixed ordering.
+ */
+bool CPPClosureType::
+is_less(const CPPDeclaration *other) const {
+  return (this < other);
+}

+ 65 - 0
dtool/src/cppparser/cppClosureType.h

@@ -0,0 +1,65 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file cppClosureType.h
+ * @author rdb
+ * @date 2017-01-14
+ */
+
+#ifndef CPPCLOSURETYPE_H
+#define CPPCLOSURETYPE_H
+
+#include "dtoolbase.h"
+
+#include "cppFunctionType.h"
+
+/**
+ * The type of a lambda expression.  This is like a function, but with
+ * additional captures defined.
+ */
+class CPPClosureType : public CPPFunctionType {
+public:
+  enum CaptureType {
+    CT_none,
+    CT_by_reference,
+    CT_by_value,
+  };
+
+  CPPClosureType(CaptureType default_capture = CT_none);
+  CPPClosureType(const CPPClosureType &copy);
+  void operator = (const CPPClosureType &copy);
+
+  struct Capture {
+    string _name;
+    CaptureType _type;
+    CPPExpression *_initializer;
+  };
+  typedef vector<Capture> Captures;
+  Captures _captures;
+
+  CaptureType _default_capture;
+
+  void add_capture(string name, CaptureType type, CPPExpression *initializer = NULL);
+
+  virtual bool is_fully_specified() const;
+
+  virtual bool is_default_constructible() const;
+  virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
+
+  virtual void output(ostream &out, int indent_level, CPPScope *scope,
+                      bool complete) const;
+  virtual SubType get_subtype() const;
+  virtual CPPClosureType *as_closure_type();
+
+protected:
+  virtual bool is_equal(const CPPDeclaration *other) const;
+  virtual bool is_less(const CPPDeclaration *other) const;
+};
+
+#endif

+ 42 - 1
dtool/src/cppparser/cppConstType.cxx

@@ -86,6 +86,22 @@ is_tbd() const {
   return _wrapped_around->is_tbd();
   return _wrapped_around->is_tbd();
 }
 }
 
 
+/**
+ * Returns true if the type is considered a fundamental type.
+ */
+bool CPPConstType::
+is_fundamental() const {
+  return _wrapped_around->is_fundamental();
+}
+
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPConstType::
+is_standard_layout() const {
+  return _wrapped_around->is_standard_layout();
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -94,12 +110,20 @@ is_trivial() const {
   return _wrapped_around->is_trivial();
   return _wrapped_around->is_trivial();
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPConstType::
+is_constructible(const CPPType *given_type) const {
+  return _wrapped_around->is_constructible(given_type);
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
 bool CPPConstType::
 bool CPPConstType::
 is_default_constructible() const {
 is_default_constructible() const {
-  return false;
+  return _wrapped_around->is_default_constructible();
 }
 }
 
 
 /**
 /**
@@ -110,6 +134,23 @@ is_copy_constructible() const {
   return _wrapped_around->is_copy_constructible();
   return _wrapped_around->is_copy_constructible();
 }
 }
 
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPConstType::
+is_destructible() const {
+  return _wrapped_around->is_destructible();
+}
+
+/**
+ * Returns true if variables of this type may be implicitly converted to
+ * the other type.
+ */
+bool CPPConstType::
+is_convertible_to(const CPPType *other) const {
+  return _wrapped_around->is_convertible_to(other);
+}
+
 /**
 /**
  * This is a little more forgiving than is_equal(): it returns true if the
  * This is a little more forgiving than is_equal(): it returns true if the
  * types appear to be referring to the same thing, even if they may have
  * types appear to be referring to the same thing, even if they may have

+ 5 - 0
dtool/src/cppparser/cppConstType.h

@@ -36,9 +36,14 @@ public:
                                 CPPScope *global_scope);
                                 CPPScope *global_scope);
 
 
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_fundamental() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
+  virtual bool is_convertible_to(const CPPType *other) const;
   virtual bool is_equivalent(const CPPType &other) const;
   virtual bool is_equivalent(const CPPType &other) const;
 
 
   virtual void output(ostream &out, int indent_level, CPPScope *scope,
   virtual void output(ostream &out, int indent_level, CPPScope *scope,

+ 16 - 2
dtool/src/cppparser/cppDeclaration.cxx

@@ -41,8 +41,13 @@ CPPDeclaration(const CPPDeclaration &copy) :
 /**
 /**
  *
  *
  */
  */
-CPPDeclaration::
-~CPPDeclaration() {
+CPPDeclaration &CPPDeclaration::
+operator = (const CPPDeclaration &copy) {
+  _vis = copy._vis;
+  _template_scope = copy._template_scope;
+  _file = copy._file;
+  _leading_comment = copy._leading_comment;
+  return *this;
 }
 }
 
 
 /**
 /**
@@ -124,6 +129,7 @@ CPPDeclaration *CPPDeclaration::
 substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
 substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
   SubstDecl::const_iterator si = subst.find(this);
   SubstDecl::const_iterator si = subst.find(this);
   if (si != subst.end()) {
   if (si != subst.end()) {
+    assert((*si).second != NULL);
     return (*si).second;
     return (*si).second;
   }
   }
   return this;
   return this;
@@ -305,6 +311,14 @@ as_make_seq() {
   return (CPPMakeSeq *)NULL;
   return (CPPMakeSeq *)NULL;
 }
 }
 
 
+/**
+ *
+ */
+CPPClosureType *CPPDeclaration::
+as_closure_type() {
+  return (CPPClosureType *)NULL;
+}
+
 /**
 /**
  * Called by CPPDeclaration to determine whether this type is equivalent to
  * Called by CPPDeclaration to determine whether this type is equivalent to
  * another type of the same type.
  * another type of the same type.

+ 76 - 1
dtool/src/cppparser/cppDeclaration.h

@@ -48,6 +48,7 @@ class CPPEnumType;
 class CPPTypeProxy;
 class CPPTypeProxy;
 class CPPMakeProperty;
 class CPPMakeProperty;
 class CPPMakeSeq;
 class CPPMakeSeq;
+class CPPClosureType;
 class CPPClassTemplateParameter;
 class CPPClassTemplateParameter;
 class CPPTBDType;
 class CPPTBDType;
 class CPPScope;
 class CPPScope;
@@ -85,11 +86,14 @@ public:
     ST_tbd,
     ST_tbd,
     ST_type_proxy,
     ST_type_proxy,
     ST_typedef,
     ST_typedef,
+    ST_closure,
   };
   };
 
 
   CPPDeclaration(const CPPFile &file);
   CPPDeclaration(const CPPFile &file);
   CPPDeclaration(const CPPDeclaration &copy);
   CPPDeclaration(const CPPDeclaration &copy);
-  virtual ~CPPDeclaration();
+  virtual ~CPPDeclaration() {};
+
+  CPPDeclaration &operator = (const CPPDeclaration &copy);
 
 
   bool operator == (const CPPDeclaration &other) const;
   bool operator == (const CPPDeclaration &other) const;
   bool operator != (const CPPDeclaration &other) const;
   bool operator != (const CPPDeclaration &other) const;
@@ -138,6 +142,77 @@ public:
   virtual CPPTypeProxy *as_type_proxy();
   virtual CPPTypeProxy *as_type_proxy();
   virtual CPPMakeProperty *as_make_property();
   virtual CPPMakeProperty *as_make_property();
   virtual CPPMakeSeq *as_make_seq();
   virtual CPPMakeSeq *as_make_seq();
+  virtual CPPClosureType *as_closure_type();
+
+  inline const CPPInstance *as_instance() const {
+    return ((CPPDeclaration *)this)->as_instance();
+  }
+  inline const CPPClassTemplateParameter *as_class_template_parameter() const {
+    return ((CPPDeclaration *)this)->as_class_template_parameter();
+  }
+  inline const CPPTypedefType *as_typedef_type() const {
+    return ((CPPDeclaration *)this)->as_typedef_type();
+  }
+  inline const CPPTypeDeclaration *as_type_declaration() const {
+    return ((CPPDeclaration *)this)->as_type_declaration();
+  }
+  inline const CPPExpression *as_expression() const {
+    return ((CPPDeclaration *)this)->as_expression();
+  }
+  inline const CPPType *as_type() const {
+    return ((CPPDeclaration *)this)->as_type();
+  }
+  inline const CPPNamespace *as_namespace() const {
+    return ((CPPDeclaration *)this)->as_namespace();
+  }
+  inline const CPPUsing *as_using() const {
+    return ((CPPDeclaration *)this)->as_using();
+  }
+  inline const CPPSimpleType *as_simple_type() const {
+    return ((CPPDeclaration *)this)->as_simple_type();
+  }
+  inline const CPPPointerType *as_pointer_type() const {
+    return ((CPPDeclaration *)this)->as_pointer_type();
+  }
+  inline const CPPReferenceType *as_reference_type() const {
+    return ((CPPDeclaration *)this)->as_reference_type();
+  }
+  inline const CPPArrayType *as_array_type() const {
+    return ((CPPDeclaration *)this)->as_array_type();
+  }
+  inline const CPPConstType *as_const_type() const {
+    return ((CPPDeclaration *)this)->as_const_type();
+  }
+  inline const CPPFunctionType *as_function_type() const {
+    return ((CPPDeclaration *)this)->as_function_type();
+  }
+  inline const CPPFunctionGroup *as_function_group() const {
+    return ((CPPDeclaration *)this)->as_function_group();
+  }
+  inline const CPPExtensionType *as_extension_type() const {
+    return ((CPPDeclaration *)this)->as_extension_type();
+  }
+  inline const CPPStructType *as_struct_type() const {
+    return ((CPPDeclaration *)this)->as_struct_type();
+  }
+  inline const CPPEnumType *as_enum_type() const {
+    return ((CPPDeclaration *)this)->as_enum_type();
+  }
+  inline const CPPTBDType *as_tbd_type() const {
+    return ((CPPDeclaration *)this)->as_tbd_type();
+  }
+  inline const CPPTypeProxy *as_type_proxy() const {
+    return ((CPPDeclaration *)this)->as_type_proxy();
+  }
+  inline const CPPMakeProperty *as_make_property() const {
+    return ((CPPDeclaration *)this)->as_make_property();
+  }
+  inline const CPPMakeSeq *as_make_seq() const {
+    return ((CPPDeclaration *)this)->as_make_seq();
+  }
+  inline const CPPClosureType *as_closure_type() const {
+    return ((CPPDeclaration *)this)->as_closure_type();
+  }
 
 
   CPPVisibility _vis;
   CPPVisibility _vis;
   CPPTemplateScope *_template_scope;
   CPPTemplateScope *_template_scope;

+ 309 - 10
dtool/src/cppparser/cppExpression.cxx

@@ -24,6 +24,8 @@
 #include "cppInstance.h"
 #include "cppInstance.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionType.h"
 #include "cppFunctionType.h"
+#include "cppClosureType.h"
+#include "cppStructType.h"
 #include "cppBison.h"
 #include "cppBison.h"
 #include "pdtoa.h"
 #include "pdtoa.h"
 
 
@@ -255,13 +257,12 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
       _u._variable = inst;
       _u._variable = inst;
       return;
       return;
     }
     }
-    // Actually, we can't scope function groups.
-    /*CPPFunctionGroup *fgroup = decl->as_function_group();
+    CPPFunctionGroup *fgroup = decl->as_function_group();
     if (fgroup != NULL) {
     if (fgroup != NULL) {
       _type = T_function;
       _type = T_function;
       _u._fgroup = fgroup;
       _u._fgroup = fgroup;
       return;
       return;
-    }*/
+    }
   }
   }
 
 
   _type = T_unknown_ident;
   _type = T_unknown_ident;
@@ -345,6 +346,22 @@ construct_op(CPPType *type, CPPExpression *op1) {
   return expr;
   return expr;
 }
 }
 
 
+/**
+ * Creates an expression that represents an aggregate initialization.
+ */
+CPPExpression CPPExpression::
+aggregate_init_op(CPPType *type, CPPExpression *op1) {
+  CPPExpression expr(0);
+  if (op1 == NULL) {
+    expr._type = T_empty_aggregate_init;
+  } else {
+    expr._type = T_aggregate_init;
+  }
+  expr._u._typecast._to = type;
+  expr._u._typecast._op1 = op1;
+  return expr;
+}
+
 /**
 /**
  * Creates an expression that represents a use of the new operator.
  * Creates an expression that represents a use of the new operator.
  */
  */
@@ -389,6 +406,19 @@ typeid_op(CPPExpression *op1, CPPType *std_type_info) {
   return expr;
   return expr;
 }
 }
 
 
+/**
+ * Creates an expression that returns a particular type trait.
+ */
+CPPExpression CPPExpression::
+type_trait(int trait, CPPType *type, CPPType *arg) {
+  CPPExpression expr(0);
+  expr._type = T_type_trait;
+  expr._u._type_trait._trait = trait;
+  expr._u._type_trait._type = type;
+  expr._u._type_trait._arg = arg;
+  return expr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -401,6 +431,17 @@ sizeof_func(CPPType *type) {
   return expr;
   return expr;
 }
 }
 
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+sizeof_ellipsis_func(CPPIdentifier *ident) {
+  CPPExpression expr(0);
+  expr._type = T_sizeof_ellipsis;
+  expr._u._ident = ident;
+  return expr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -413,6 +454,17 @@ alignof_func(CPPType *type) {
   return expr;
   return expr;
 }
 }
 
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+lambda(CPPClosureType *type) {
+  CPPExpression expr(0);
+  expr._type = T_lambda;
+  expr._u._closure_type = type;
+  return expr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -492,13 +544,6 @@ get_delete() {
   return expr;
   return expr;
 }
 }
 
 
-/**
- *
- */
-CPPExpression::
-~CPPExpression() {
-}
-
 /**
 /**
  *
  *
  */
  */
@@ -576,9 +621,12 @@ evaluate() const {
 
 
   case T_construct:
   case T_construct:
   case T_default_construct:
   case T_default_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
   case T_new:
   case T_new:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
+  case T_sizeof_ellipsis:
     return Result();
     return Result();
 
 
   case T_alignof:
   case T_alignof:
@@ -801,6 +849,95 @@ evaluate() const {
   case T_typeid_expr:
   case T_typeid_expr:
     return Result();
     return Result();
 
 
+  case T_type_trait:
+    switch (_u._type_trait._trait) {
+    case KW_HAS_VIRTUAL_DESTRUCTOR:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->has_virtual_destructor());
+      }
+
+    case KW_IS_ABSTRACT:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_abstract());
+      }
+
+    case KW_IS_BASE_OF:
+      {
+        CPPStructType *struct_type1 = _u._type_trait._type->as_struct_type();
+        CPPStructType *struct_type2 = _u._type_trait._arg->as_struct_type();
+        return Result(struct_type1 != NULL && struct_type2 != NULL && struct_type1->is_base_of(struct_type2));
+      }
+
+    case KW_IS_CLASS:
+      {
+        CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
+        return Result(ext_type != NULL && (
+          ext_type->_type == CPPExtensionType::T_class ||
+          ext_type->_type == CPPExtensionType::T_struct));
+      }
+
+    case KW_IS_CONSTRUCTIBLE:
+      if (_u._type_trait._arg == NULL) {
+        return Result(_u._type_trait._type->is_default_constructible());
+      } else {
+        return Result(_u._type_trait._type->is_constructible(_u._type_trait._arg));
+      }
+
+    case KW_IS_CONVERTIBLE_TO:
+      assert(_u._type_trait._arg != NULL);
+      return Result(_u._type_trait._type->is_convertible_to(_u._type_trait._arg));
+
+    case KW_IS_DESTRUCTIBLE:
+      return Result(_u._type_trait._type->is_destructible());
+
+    case KW_IS_EMPTY:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_empty());
+      }
+
+    case KW_IS_ENUM:
+      return Result(_u._type_trait._type->is_enum());
+
+    case KW_IS_FINAL:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_final());
+      }
+
+    case KW_IS_FUNDAMENTAL:
+      return Result(_u._type_trait._type->is_fundamental());
+
+    case KW_IS_POD:
+      return Result(_u._type_trait._type->is_trivial() &&
+                    _u._type_trait._type->is_standard_layout());
+
+    case KW_IS_POLYMORPHIC:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_polymorphic());
+      }
+
+    case KW_IS_STANDARD_LAYOUT:
+      return Result(_u._type_trait._type->is_standard_layout());
+
+    case KW_IS_TRIVIAL:
+      return Result(_u._type_trait._type->is_trivial());
+
+    case KW_IS_UNION:
+      {
+        CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
+        return Result(ext_type != NULL &&
+          ext_type->_type == CPPExtensionType::T_union);
+      }
+
+    default:
+      cerr << "**unexpected type trait**\n";
+      abort();
+    }
+
   default:
   default:
     cerr << "**invalid operand**\n";
     cerr << "**invalid operand**\n";
     abort();
     abort();
@@ -909,6 +1046,8 @@ determine_type() const {
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
   case T_default_construct:
   case T_default_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
     return _u._typecast._to;
     return _u._typecast._to;
 
 
   case T_new:
   case T_new:
@@ -916,6 +1055,7 @@ determine_type() const {
     return CPPType::new_type(new CPPPointerType(_u._typecast._to));
     return CPPType::new_type(new CPPPointerType(_u._typecast._to));
 
 
   case T_sizeof:
   case T_sizeof:
+  case T_sizeof_ellipsis:
   case T_alignof:
   case T_alignof:
     // Note: this should actually be size_t, but that is defined as a typedef
     // Note: this should actually be size_t, but that is defined as a typedef
     // in parser-inc.  We could try to resolve it, but that's hacky.  Eh, it's
     // in parser-inc.  We could try to resolve it, but that's hacky.  Eh, it's
@@ -1026,10 +1166,28 @@ determine_type() const {
 
 
     case 'f': // Function evaluation
     case 'f': // Function evaluation
       if (t1 != NULL) {
       if (t1 != NULL) {
+        // Easy case, function with only a single overload.
         CPPFunctionType *ftype = t1->as_function_type();
         CPPFunctionType *ftype = t1->as_function_type();
         if (ftype != (CPPFunctionType *)NULL) {
         if (ftype != (CPPFunctionType *)NULL) {
           return ftype->_return_type;
           return ftype->_return_type;
         }
         }
+      } else if (_u._op._op1->_type == T_function) {
+        CPPFunctionGroup *fgroup = _u._op._op1->_u._fgroup;
+        if (_u._op._op2 == NULL) {
+          // If we are passing no args, look for an overload that has takes no
+          // args.
+          for (auto it = fgroup->_instances.begin(); it != fgroup->_instances.end(); ++it) {
+            CPPInstance *inst = *it;
+            if (inst != NULL && inst->_type != NULL) {
+              CPPFunctionType *type = inst->_type->as_function_type();
+              if (type != NULL && type->accepts_num_parameters(0)) {
+                return type->_return_type;
+              }
+            }
+          }
+        } else {
+          //TODO
+        }
       }
       }
       return NULL;
       return NULL;
 
 
@@ -1057,6 +1215,12 @@ determine_type() const {
   case T_typeid_expr:
   case T_typeid_expr:
     return _u._typeid._std_type_info;
     return _u._typeid._std_type_info;
 
 
+  case T_type_trait:
+    return bool_type;
+
+  case T_lambda:
+    return _u._closure_type;
+
   default:
   default:
     cerr << "**invalid operand**\n";
     cerr << "**invalid operand**\n";
     abort();
     abort();
@@ -1103,16 +1267,21 @@ is_fully_specified() const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     return (_u._typecast._to->is_fully_specified() &&
     return (_u._typecast._to->is_fully_specified() &&
             _u._typecast._op1->is_fully_specified());
             _u._typecast._op1->is_fully_specified());
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
     return _u._typecast._to->is_fully_specified();
     return _u._typecast._to->is_fully_specified();
 
 
+  case T_sizeof_ellipsis:
+    return _u._ident->is_fully_specified();
+
   case T_trinary_operation:
   case T_trinary_operation:
     if (!_u._op._op3->is_fully_specified()) {
     if (!_u._op._op3->is_fully_specified()) {
       return false;
       return false;
@@ -1141,6 +1310,12 @@ is_fully_specified() const {
   case T_typeid_expr:
   case T_typeid_expr:
     return _u._typeid._expr->is_fully_specified();
     return _u._typeid._expr->is_fully_specified();
 
 
+  case T_type_trait:
+    return _u._type_trait._type->is_fully_specified();
+
+  case T_lambda:
+    return _u._closure_type->is_fully_specified();
+
   default:
   default:
     return true;
     return true;
   }
   }
@@ -1224,6 +1399,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     rep->_u._typecast._op1 =
     rep->_u._typecast._op1 =
       _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
       _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
@@ -1232,6 +1408,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     // fall through
     // fall through
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -1276,6 +1453,13 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr);
     any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr);
     break;
     break;
 
 
+  case T_type_trait:
+    rep->_u._type_trait._type =
+      _u._type_trait._type->substitute_decl(subst, current_scope, global_scope)
+      ->as_type();
+    any_changed = any_changed || (rep->_u._type_trait._type != _u._type_trait._type);
+    break;
+
   default:
   default:
     break;
     break;
   }
   }
@@ -1319,6 +1503,8 @@ is_tbd() const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
   case T_new:
   case T_new:
   case T_default_construct:
   case T_default_construct:
   case T_default_new:
   case T_default_new:
@@ -1350,6 +1536,12 @@ is_tbd() const {
   case T_typeid_expr:
   case T_typeid_expr:
     return _u._typeid._expr->is_tbd();
     return _u._typeid._expr->is_tbd();
 
 
+  case T_type_trait:
+    return _u._type_trait._type->is_tbd();
+
+  case T_lambda:
+    return _u._closure_type->is_tbd();
+
   default:
   default:
     return false;
     return false;
   }
   }
@@ -1430,6 +1622,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
           out << "\\\"";
           out << "\\\"";
           break;
           break;
 
 
+        case '\\':
+          out << "\\\\";
+          break;
+
         default:
         default:
           if (isprint(*si)) {
           if (isprint(*si)) {
             out << *si;
             out << *si;
@@ -1521,6 +1717,18 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "()";
     out << "()";
     break;
     break;
 
 
+  case T_aggregate_init:
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "{";
+    _u._typecast._op1->output(out, indent_level, scope, false);
+    out << "}";
+    break;
+
+  case T_empty_aggregate_init:
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "{}";
+    break;
+
   case T_new:
   case T_new:
     out << "(new ";
     out << "(new ";
     _u._typecast._to->output(out, indent_level, scope, false);
     _u._typecast._to->output(out, indent_level, scope, false);
@@ -1541,6 +1749,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << ")";
     out << ")";
     break;
     break;
 
 
+  case T_sizeof_ellipsis:
+    out << "sizeof...(";
+    _u._ident->output(out, scope);
+    out << ")";
+    break;
+
   case T_alignof:
   case T_alignof:
     out << "alignof(";
     out << "alignof(";
     _u._typecast._to->output(out, indent_level, scope, false);
     _u._typecast._to->output(out, indent_level, scope, false);
@@ -1753,6 +1967,69 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "delete";
     out << "delete";
     break;
     break;
 
 
+  case T_type_trait:
+    switch (_u._type_trait._trait) {
+    case KW_HAS_VIRTUAL_DESTRUCTOR:
+      out << "__has_virtual_destructor";
+      break;
+    case KW_IS_ABSTRACT:
+      out << "__is_abstract";
+      break;
+    case KW_IS_BASE_OF:
+      out << "__is_base_of";
+      break;
+    case KW_IS_CLASS:
+      out << "__is_class";
+      break;
+    case KW_IS_CONSTRUCTIBLE:
+      out << "__is_constructible";
+      break;
+    case KW_IS_CONVERTIBLE_TO:
+      out << "__is_convertible_to";
+      break;
+    case KW_IS_DESTRUCTIBLE:
+      out << "__is_destructible";
+      break;
+    case KW_IS_EMPTY:
+      out << "__is_empty";
+      break;
+    case KW_IS_ENUM:
+      out << "__is_enum";
+      break;
+    case KW_IS_FINAL:
+      out << "__is_final";
+      break;
+    case KW_IS_FUNDAMENTAL:
+      out << "__is_fundamental";
+      break;
+    case KW_IS_POD:
+      out << "__is_pod";
+      break;
+    case KW_IS_POLYMORPHIC:
+      out << "__is_polymorphic";
+      break;
+    case KW_IS_STANDARD_LAYOUT:
+      out << "__is_standard_layout";
+      break;
+    case KW_IS_TRIVIAL:
+      out << "__is_trivial";
+      break;
+    case KW_IS_UNION:
+      out << "__is_union";
+      break;
+    default:
+      out << (evaluate().as_boolean() ? "true" : "false");
+      return;
+    }
+    out << '(';
+    _u._type_trait._type->output(out, indent_level, scope, false);
+    out << ')';
+    break;
+
+  case T_lambda:
+    _u._closure_type->output(out, indent_level, scope, false);
+    break;
+
   default:
   default:
     out << "(** invalid operand type " << (int)_type << " **)";
     out << "(** invalid operand type " << (int)_type << " **)";
   }
   }
@@ -1864,6 +2141,7 @@ is_equal(const CPPDeclaration *other) const {
     return _u._fgroup == ot->_u._fgroup;
     return _u._fgroup == ot->_u._fgroup;
 
 
   case T_unknown_ident:
   case T_unknown_ident:
+  case T_sizeof_ellipsis:
     return *_u._ident == *ot->_u._ident;
     return *_u._ident == *ot->_u._ident;
 
 
   case T_typecast:
   case T_typecast:
@@ -1872,11 +2150,13 @@ is_equal(const CPPDeclaration *other) const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     return _u._typecast._to == ot->_u._typecast._to &&
     return _u._typecast._to == ot->_u._typecast._to &&
       *_u._typecast._op1 == *ot->_u._typecast._op1;
       *_u._typecast._op1 == *ot->_u._typecast._op1;
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -1907,6 +2187,13 @@ is_equal(const CPPDeclaration *other) const {
   case T_typeid_expr:
   case T_typeid_expr:
     return _u._typeid._expr == ot->_u._typeid._expr;
     return _u._typeid._expr == ot->_u._typeid._expr;
 
 
+  case T_type_trait:
+    return _u._type_trait._trait == ot->_u._type_trait._trait &&
+           _u._type_trait._type == ot->_u._type_trait._type;
+
+  case T_lambda:
+    return _u._closure_type == ot->_u._closure_type;
+
   default:
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }
   }
@@ -1954,6 +2241,7 @@ is_less(const CPPDeclaration *other) const {
     return *_u._fgroup < *ot->_u._fgroup;
     return *_u._fgroup < *ot->_u._fgroup;
 
 
   case T_unknown_ident:
   case T_unknown_ident:
+  case T_sizeof_ellipsis:
     return *_u._ident < *ot->_u._ident;
     return *_u._ident < *ot->_u._ident;
 
 
   case T_typecast:
   case T_typecast:
@@ -1962,6 +2250,7 @@ is_less(const CPPDeclaration *other) const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     if (_u._typecast._to != ot->_u._typecast._to) {
     if (_u._typecast._to != ot->_u._typecast._to) {
       return _u._typecast._to < ot->_u._typecast._to;
       return _u._typecast._to < ot->_u._typecast._to;
@@ -1969,6 +2258,7 @@ is_less(const CPPDeclaration *other) const {
     return *_u._typecast._op1 < *ot->_u._typecast._op1;
     return *_u._typecast._op1 < *ot->_u._typecast._op1;
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -2007,6 +2297,15 @@ is_less(const CPPDeclaration *other) const {
   case T_typeid_expr:
   case T_typeid_expr:
     return *_u._typeid._expr < *ot->_u._typeid._expr;
     return *_u._typeid._expr < *ot->_u._typeid._expr;
 
 
+  case T_type_trait:
+    if (_u._type_trait._trait != ot->_u._type_trait._trait) {
+      return _u._type_trait._trait < ot->_u._type_trait._trait;
+    }
+    return *_u._type_trait._type < *ot->_u._type_trait._type;
+
+  case T_lambda:
+    return _u._closure_type < ot->_u._closure_type;
+
   default:
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }
   }

+ 15 - 2
dtool/src/cppparser/cppExpression.h

@@ -48,9 +48,12 @@ public:
     T_reinterpret_cast,
     T_reinterpret_cast,
     T_construct,
     T_construct,
     T_default_construct,
     T_default_construct,
+    T_aggregate_init,
+    T_empty_aggregate_init,
     T_new,
     T_new,
     T_default_new,
     T_default_new,
     T_sizeof,
     T_sizeof,
+    T_sizeof_ellipsis,
     T_alignof,
     T_alignof,
     T_unary_operation,
     T_unary_operation,
     T_binary_operation,
     T_binary_operation,
@@ -59,6 +62,8 @@ public:
     T_raw_literal,
     T_raw_literal,
     T_typeid_type,
     T_typeid_type,
     T_typeid_expr,
     T_typeid_expr,
+    T_type_trait,
+    T_lambda,
 
 
     // These are used when parsing =default and =delete methods.
     // These are used when parsing =default and =delete methods.
     T_default,
     T_default,
@@ -78,11 +83,15 @@ public:
 
 
   static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast);
   static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast);
   static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
   static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
+  static CPPExpression aggregate_init_op(CPPType *type, CPPExpression *op1);
   static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
   static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
   static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
+  static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = NULL);
   static CPPExpression sizeof_func(CPPType *type);
   static CPPExpression sizeof_func(CPPType *type);
+  static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression alignof_func(CPPType *type);
   static CPPExpression alignof_func(CPPType *type);
+  static CPPExpression lambda(CPPClosureType *type);
 
 
   static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
   static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
   static CPPExpression literal(long double value, CPPInstance *lit_op);
   static CPPExpression literal(long double value, CPPInstance *lit_op);
@@ -93,8 +102,6 @@ public:
   static const CPPExpression &get_default();
   static const CPPExpression &get_default();
   static const CPPExpression &get_delete();
   static const CPPExpression &get_delete();
 
 
-  ~CPPExpression();
-
   enum ResultType {
   enum ResultType {
     RT_integer,
     RT_integer,
     RT_real,
     RT_real,
@@ -148,6 +155,7 @@ public:
     CPPInstance *_variable;
     CPPInstance *_variable;
     CPPFunctionGroup *_fgroup;
     CPPFunctionGroup *_fgroup;
     CPPIdentifier *_ident;
     CPPIdentifier *_ident;
+    CPPClosureType *_closure_type;
     struct {
     struct {
       union {
       union {
         CPPType *_type;
         CPPType *_type;
@@ -170,6 +178,11 @@ public:
       CPPInstance *_operator;
       CPPInstance *_operator;
       CPPExpression *_value;
       CPPExpression *_value;
     } _literal;
     } _literal;
+    struct {
+      int _trait;
+      CPPType *_type;
+      CPPType *_arg;
+    } _type_trait;
   } _u;
   } _u;
 
 
 protected:
 protected:

+ 23 - 3
dtool/src/cppparser/cppExtensionType.cxx

@@ -87,12 +87,32 @@ is_tbd() const {
   return false;
   return false;
 }
 }
 
 
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPExtensionType::
+is_standard_layout() const {
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
 bool CPPExtensionType::
 bool CPPExtensionType::
 is_trivial() const {
 is_trivial() const {
-  return (_type == T_enum);
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
+}
+
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPExtensionType::
+is_constructible(const CPPType *given_type) const {
+  if (_type == T_enum || _type == T_enum_class || _type == T_enum_struct) {
+    const CPPExtensionType *other = ((CPPType *)given_type)->remove_reference()->remove_const()->as_extension_type();
+    return other != NULL && is_equal(other);
+  }
+  return false;
 }
 }
 
 
 /**
 /**
@@ -100,7 +120,7 @@ is_trivial() const {
  */
  */
 bool CPPExtensionType::
 bool CPPExtensionType::
 is_default_constructible() const {
 is_default_constructible() const {
-  return (_type == T_enum);
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
 }
 }
 
 
 /**
 /**
@@ -108,7 +128,7 @@ is_default_constructible() const {
  */
  */
 bool CPPExtensionType::
 bool CPPExtensionType::
 is_copy_constructible() const {
 is_copy_constructible() const {
-  return (_type == T_enum);
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
 }
 }
 
 
 /**
 /**

+ 2 - 0
dtool/src/cppparser/cppExtensionType.h

@@ -47,7 +47,9 @@ public:
 
 
   virtual bool is_incomplete() const;
   virtual bool is_incomplete() const;
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
 
 

+ 1 - 1
dtool/src/cppparser/cppFile.h

@@ -55,7 +55,7 @@ public:
 
 
   Filename _filename;
   Filename _filename;
   Filename _filename_as_referenced;
   Filename _filename_as_referenced;
-  Source _source;
+  mutable Source _source;
   mutable bool _pragma_once;
   mutable bool _pragma_once;
 };
 };
 
 

+ 67 - 14
dtool/src/cppparser/cppFunctionType.cxx

@@ -31,7 +31,8 @@ CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
 
 
   // If the parameter list contains just the token "void", it means no
   // If the parameter list contains just the token "void", it means no
   // parameters.
   // parameters.
-  if (_parameters->_parameters.size() == 1 &&
+  if (_parameters != NULL &&
+      _parameters->_parameters.size() == 1 &&
       _parameters->_parameters.front()->_type->as_simple_type() != NULL &&
       _parameters->_parameters.front()->_type->as_simple_type() != NULL &&
       _parameters->_parameters.front()->_type->as_simple_type()->_type ==
       _parameters->_parameters.front()->_type->as_simple_type()->_type ==
       CPPSimpleType::T_void &&
       CPPSimpleType::T_void &&
@@ -65,6 +66,31 @@ operator = (const CPPFunctionType &copy) {
   _class_owner = copy._class_owner;
   _class_owner = copy._class_owner;
 }
 }
 
 
+/**
+ * Returns true if the function accepts the given number of parameters.
+ */
+bool CPPFunctionType::
+accepts_num_parameters(int num_parameters) {
+  if (_parameters == NULL) {
+    return (num_parameters == 0);
+  }
+  size_t actual_num_parameters = _parameters->_parameters.size();
+  // If we passed too many parameters, it must have an ellipsis.
+  if (num_parameters > actual_num_parameters) {
+    return _parameters->_includes_ellipsis;
+  }
+
+  // Make sure all superfluous parameters have a default value.
+  for (size_t i = num_parameters; i < actual_num_parameters; ++i) {
+    CPPInstance *param = _parameters->_parameters[i];
+    if (param->_initializer == NULL) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 /**
 /**
  * Returns true if this declaration is an actual, factual declaration, or
  * Returns true if this declaration is an actual, factual declaration, or
  * false if some part of the declaration depends on a template parameter which
  * false if some part of the declaration depends on a template parameter which
@@ -89,12 +115,16 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   }
   }
 
 
   CPPFunctionType *rep = new CPPFunctionType(*this);
   CPPFunctionType *rep = new CPPFunctionType(*this);
-  rep->_return_type =
-    _return_type->substitute_decl(subst, current_scope, global_scope)
-    ->as_type();
+  if (_return_type != NULL) {
+    rep->_return_type =
+      _return_type->substitute_decl(subst, current_scope, global_scope)
+      ->as_type();
+  }
 
 
-  rep->_parameters =
-    _parameters->substitute_decl(subst, current_scope, global_scope);
+  if (_parameters != NULL) {
+    rep->_parameters =
+      _parameters->substitute_decl(subst, current_scope, global_scope);
+  }
 
 
   if (rep->_return_type == _return_type &&
   if (rep->_return_type == _return_type &&
       rep->_parameters == _parameters) {
       rep->_parameters == _parameters) {
@@ -115,8 +145,12 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
 CPPType *CPPFunctionType::
 CPPType *CPPFunctionType::
 resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
 resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
   CPPType *rtype = _return_type->resolve_type(current_scope, global_scope);
   CPPType *rtype = _return_type->resolve_type(current_scope, global_scope);
-  CPPParameterList *params =
-    _parameters->resolve_type(current_scope, global_scope);
+  CPPParameterList *params;
+  if (_parameters == NULL) {
+    params = NULL;
+  } else {
+    params = _parameters->resolve_type(current_scope, global_scope);
+  }
 
 
   if (rtype != _return_type || params != _parameters) {
   if (rtype != _return_type || params != _parameters) {
     CPPFunctionType *rep = new CPPFunctionType(*this);
     CPPFunctionType *rep = new CPPFunctionType(*this);
@@ -137,7 +171,7 @@ is_tbd() const {
   if (_return_type->is_tbd()) {
   if (_return_type->is_tbd()) {
     return true;
     return true;
   }
   }
-  return _parameters->is_tbd();
+  return _parameters == NULL || _parameters->is_tbd();
 }
 }
 
 
 /**
 /**
@@ -265,6 +299,9 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
   if (_flags & F_const_method) {
   if (_flags & F_const_method) {
     out << " const";
     out << " const";
   }
   }
+  if (_flags & F_volatile_method) {
+    out << " volatile";
+  }
   if (_flags & F_noexcept) {
   if (_flags & F_noexcept) {
     out << " noexcept";
     out << " noexcept";
   }
   }
@@ -289,6 +326,10 @@ get_num_default_parameters() const {
   // The trick is just to count, beginning from the end and working towards
   // The trick is just to count, beginning from the end and working towards
   // the front, the number of parameters that have some initializer.
   // the front, the number of parameters that have some initializer.
 
 
+  if (_parameters == NULL) {
+    return 0;
+  }
+
   const CPPParameterList::Parameters &params = _parameters->_parameters;
   const CPPParameterList::Parameters &params = _parameters->_parameters;
   CPPParameterList::Parameters::const_reverse_iterator pi;
   CPPParameterList::Parameters::const_reverse_iterator pi;
   int count = 0;
   int count = 0;
@@ -321,14 +362,17 @@ as_function_type() {
  * This is similar to is_equal(), except it is more forgiving: it considers
  * This is similar to is_equal(), except it is more forgiving: it considers
  * the functions to be equivalent only if the return type and the types of all
  * the functions to be equivalent only if the return type and the types of all
  * parameters match.
  * parameters match.
+ *
+ * Note that this isn't symmetric to account for covariant return types.
  */
  */
 bool CPPFunctionType::
 bool CPPFunctionType::
-is_equivalent_function(const CPPFunctionType &other) const {
-  if (!_return_type->is_equivalent(*other._return_type)) {
+match_virtual_override(const CPPFunctionType &other) const {
+  if (!_return_type->is_equivalent(*other._return_type) &&
+      !_return_type->is_convertible_to(other._return_type)) {
     return false;
     return false;
   }
   }
 
 
-  if (_flags != other._flags) {
+  if (((_flags ^ other._flags) & ~(F_override | F_final)) != 0) {
     return false;
     return false;
   }
   }
 
 
@@ -354,7 +398,11 @@ is_equal(const CPPDeclaration *other) const {
   if (_flags != ot->_flags) {
   if (_flags != ot->_flags) {
     return false;
     return false;
   }
   }
-  if (*_parameters != *ot->_parameters) {
+  if (_parameters == ot->_parameters) {
+    return true;
+  }
+  if (_parameters == NULL || ot->_parameters == NULL ||
+      *_parameters != *ot->_parameters) {
     return false;
     return false;
   }
   }
   return true;
   return true;
@@ -376,6 +424,11 @@ is_less(const CPPDeclaration *other) const {
   if (_flags != ot->_flags) {
   if (_flags != ot->_flags) {
     return _flags < ot->_flags;
     return _flags < ot->_flags;
   }
   }
-
+  if (_parameters == ot->_parameters) {
+    return 0;
+  }
+  if (_parameters == NULL || ot->_parameters == NULL) {
+    return _parameters < ot->_parameters;
+  }
   return *_parameters < *ot->_parameters;
   return *_parameters < *ot->_parameters;
 }
 }

+ 6 - 1
dtool/src/cppparser/cppFunctionType.h

@@ -40,6 +40,9 @@ public:
     F_trailing_return_type = 0x800,
     F_trailing_return_type = 0x800,
     F_final             = 0x1000,
     F_final             = 0x1000,
     F_override          = 0x2000,
     F_override          = 0x2000,
+    F_volatile_method   = 0x4000,
+    F_lvalue_method     = 0x8000,
+    F_rvalue_method     = 0x10000,
   };
   };
 
 
   CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
   CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
@@ -47,6 +50,8 @@ public:
   CPPFunctionType(const CPPFunctionType &copy);
   CPPFunctionType(const CPPFunctionType &copy);
   void operator = (const CPPFunctionType &copy);
   void operator = (const CPPFunctionType &copy);
 
 
+  bool accepts_num_parameters(int num_parameters);
+
   CPPType *_return_type;
   CPPType *_return_type;
   CPPParameterList *_parameters;
   CPPParameterList *_parameters;
   int _flags;
   int _flags;
@@ -81,7 +86,7 @@ public:
 
 
   virtual CPPFunctionType *as_function_type();
   virtual CPPFunctionType *as_function_type();
 
 
-  bool is_equivalent_function(const CPPFunctionType &other) const;
+  bool match_virtual_override(const CPPFunctionType &other) const;
 
 
   CPPIdentifier *_class_owner;
   CPPIdentifier *_class_owner;
 
 

+ 8 - 5
dtool/src/cppparser/cppInstance.cxx

@@ -82,6 +82,10 @@ CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
     // anyway.
     // anyway.
   }
   }
 
 
+  if (ii->_packed) {
+    _storage_class |= SC_parameter_pack;
+  }
+
   delete ii;
   delete ii;
 }
 }
 
 
@@ -353,11 +357,7 @@ check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) {
           CPPReferenceType *ref_type = param_type->as_reference_type();
           CPPReferenceType *ref_type = param_type->as_reference_type();
 
 
           if (ref_type != NULL) {
           if (ref_type != NULL) {
-            param_type = ref_type->_pointing_at;
-
-            if (param_type->get_subtype() == CPPDeclaration::ST_const) {
-              param_type = param_type->as_const_type()->_wrapped_around;
-            }
+            param_type = ref_type->_pointing_at->remove_cv();
 
 
             if (class_name == param_type->get_simple_name()) {
             if (class_name == param_type->get_simple_name()) {
               if (ref_type->_value_category == CPPReferenceType::VC_rvalue) {
               if (ref_type->_value_category == CPPReferenceType::VC_rvalue) {
@@ -563,6 +563,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
   if (_ident != NULL) {
   if (_ident != NULL) {
     name = _ident->get_local_name(scope);
     name = _ident->get_local_name(scope);
   }
   }
+  if (_storage_class & SC_parameter_pack) {
+    name = "..." + name;
+  }
 
 
   if (_type->as_function_type()) {
   if (_type->as_function_type()) {
     _type->as_function_type()->
     _type->as_function_type()->

+ 7 - 0
dtool/src/cppparser/cppInstance.h

@@ -64,6 +64,13 @@ public:
     SC_deleted      = 0x8000,
     SC_deleted      = 0x8000,
 
 
     SC_thread_local = 0x10000,
     SC_thread_local = 0x10000,
+
+    // This isn't really a storage class.  It's only used temporarily by the
+    // parser, to make parsing specifier sequences a bit easier.
+    SC_const        = 0x20000,
+
+    // Used to indicate that this is a parameter pack.
+    SC_parameter_pack = 0x40000,
   };
   };
 
 
   CPPInstance(CPPType *type, const string &name, int storage_class = 0);
   CPPInstance(CPPType *type, const string &name, int storage_class = 0);

+ 7 - 7
dtool/src/cppparser/cppInstanceIdentifier.cxx

@@ -26,12 +26,11 @@
  */
  */
 CPPInstanceIdentifier::Modifier::
 CPPInstanceIdentifier::Modifier::
 Modifier(CPPInstanceIdentifierType type) :
 Modifier(CPPInstanceIdentifierType type) :
-  _type(type)
-{
-  _func_params = NULL;
-  _func_flags = 0;
-  _scoping = NULL;
-  _expr = NULL;
+  _type(type),
+  _func_params(NULL),
+  _func_flags(0),
+  _scoping(NULL),
+  _expr(NULL) {
 }
 }
 
 
 /**
 /**
@@ -83,7 +82,8 @@ initializer_type(CPPParameterList *params) {
 CPPInstanceIdentifier::
 CPPInstanceIdentifier::
 CPPInstanceIdentifier(CPPIdentifier *ident) :
 CPPInstanceIdentifier(CPPIdentifier *ident) :
   _ident(ident),
   _ident(ident),
-  _bit_width(-1) {
+  _bit_width(-1),
+  _packed(false) {
 }
 }
 
 
 /**
 /**

+ 4 - 0
dtool/src/cppparser/cppInstanceIdentifier.h

@@ -88,8 +88,12 @@ public:
   typedef vector<Modifier> Modifiers;
   typedef vector<Modifier> Modifiers;
   Modifiers _modifiers;
   Modifiers _modifiers;
 
 
+  // If not -1, indicates a bitfield
   int _bit_width;
   int _bit_width;
 
 
+  // Indicates a parameter pack
+  bool _packed;
+
 private:
 private:
   CPPType *
   CPPType *
   r_unroll_type(CPPType *start_type, Modifiers::const_iterator mi);
   r_unroll_type(CPPType *start_type, Modifiers::const_iterator mi);

+ 14 - 1
dtool/src/cppparser/cppParser.cxx

@@ -45,7 +45,20 @@ is_fully_specified() const {
  */
  */
 bool CPPParser::
 bool CPPParser::
 parse_file(const Filename &filename) {
 parse_file(const Filename &filename) {
-  if (!init_cpp(CPPFile(filename, filename, CPPFile::S_local))) {
+  Filename canonical(filename);
+  canonical.make_canonical();
+
+  CPPFile file(canonical, filename, CPPFile::S_local);
+
+  // Don't read it if we included it before and it had #pragma once.
+  ParsedFiles::iterator it = _parsed_files.find(file);
+  if (it != _parsed_files.end() && it->_pragma_once) {
+    // But mark it as local.
+    it->_source = CPPFile::S_local;
+    return true;
+  }
+
+  if (!init_cpp(file)) {
     cerr << "Unable to read " << filename << "\n";
     cerr << "Unable to read " << filename << "\n";
     return false;
     return false;
   }
   }

+ 65 - 0
dtool/src/cppparser/cppPointerType.cxx

@@ -14,6 +14,9 @@
 #include "cppPointerType.h"
 #include "cppPointerType.h"
 #include "cppFunctionType.h"
 #include "cppFunctionType.h"
 #include "cppIdentifier.h"
 #include "cppIdentifier.h"
+#include "cppArrayType.h"
+#include "cppStructType.h"
+#include "cppSimpleType.h"
 
 
 /**
 /**
  *
  *
@@ -88,6 +91,14 @@ is_tbd() const {
   return _pointing_at->is_tbd();
   return _pointing_at->is_tbd();
 }
 }
 
 
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPPointerType::
+is_standard_layout() const {
+  return true;
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -96,6 +107,60 @@ is_trivial() const {
   return true;
   return true;
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPPointerType::
+is_constructible(const CPPType *given_type) const {
+  given_type = ((CPPType *)given_type)->remove_reference()->remove_cv();
+
+  // Can convert from compatible pointer or array type.
+  CPPType *other_target;
+  switch (given_type->get_subtype()) {
+  case ST_array:
+    other_target = given_type->as_array_type()->_element_type;
+    break;
+
+  case ST_pointer:
+    other_target = given_type->as_pointer_type()->_pointing_at;
+    break;
+
+  case ST_simple:
+    // Can initialize from nullptr.
+    return given_type->as_simple_type()->_type == CPPSimpleType::T_nullptr;
+
+  default:
+    return false;
+  }
+
+  // Can't convert const to non-const pointer.
+  if (other_target->is_const() && !_pointing_at->is_const()) {
+    return false;
+  }
+
+  // Are we pointing to the same type?  That's always OK.
+  const CPPType *a = _pointing_at->remove_cv();
+  const CPPType *b = other_target->remove_cv();
+  if (a == b || *a == *b) {
+    return true;
+  }
+
+  // Can initialize void pointer with any pointer.
+  const CPPSimpleType *simple_type = a->as_simple_type();
+  if (simple_type != NULL) {
+    return simple_type->_type == CPPSimpleType::T_void;
+  }
+
+  // Can initialize from derived class pointer.
+  const CPPStructType *a_struct = a->as_struct_type();
+  const CPPStructType *b_struct = b->as_struct_type();
+  if (a_struct != NULL && b_struct != NULL) {
+    return a_struct->is_base_of(b_struct);
+  }
+
+  return false;
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */

+ 2 - 0
dtool/src/cppparser/cppPointerType.h

@@ -36,7 +36,9 @@ public:
                                 CPPScope *global_scope);
                                 CPPScope *global_scope);
 
 
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *other) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_equivalent(const CPPType &other) const;
   virtual bool is_equivalent(const CPPType &other) const;

+ 327 - 88
dtool/src/cppparser/cppPreprocessor.cxx

@@ -18,6 +18,7 @@
 #include "cppIdentifier.h"
 #include "cppIdentifier.h"
 #include "cppTemplateScope.h"
 #include "cppTemplateScope.h"
 #include "cppTemplateParameterList.h"
 #include "cppTemplateParameterList.h"
+#include "cppClassTemplateParameter.h"
 #include "cppConstType.h"
 #include "cppConstType.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionType.h"
 #include "cppFunctionType.h"
@@ -208,6 +209,7 @@ CPPPreprocessor() {
   _state = S_eof;
   _state = S_eof;
   _paren_nesting = 0;
   _paren_nesting = 0;
   _parsing_template_params = false;
   _parsing_template_params = false;
+  _parsing_attribute = false;
   _unget = '\0';
   _unget = '\0';
   _last_c = '\0';
   _last_c = '\0';
   _start_of_line = true;
   _start_of_line = true;
@@ -416,7 +418,14 @@ get_next_token0() {
     int token_type = IDENTIFIER;
     int token_type = IDENTIFIER;
     CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope);
     CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope);
     if (decl != NULL && decl->as_type() != NULL) {
     if (decl != NULL && decl->as_type() != NULL) {
-      token_type = TYPENAME_IDENTIFIER;
+      // We need to see type pack template parameters as a different type of
+      // identifier to resolve a parser ambiguity.
+      CPPClassTemplateParameter *ctp = decl->as_class_template_parameter();
+      if (ctp && ctp->_packed) {
+        token_type = TYPEPACK_IDENTIFIER;
+      } else {
+        token_type = TYPENAME_IDENTIFIER;
+      }
     }
     }
 
 
     _last_token_loc = loc;
     _last_token_loc = loc;
@@ -801,6 +810,8 @@ expand_manifests(const string &input_expr, bool expand_undefined,
         // Here's an identifier.  Is it "defined"?
         // Here's an identifier.  Is it "defined"?
         if (ident == "defined") {
         if (ident == "defined") {
           expand_defined_function(expr, q, p);
           expand_defined_function(expr, q, p);
+        } else if (expand_undefined && ident == "__has_include") {
+          expand_has_include_function(expr, q, p, loc);
         } else {
         } else {
           // Is it a manifest?
           // Is it a manifest?
           Manifests::const_iterator mi = _manifests.find(ident);
           Manifests::const_iterator mi = _manifests.find(ident);
@@ -809,6 +820,20 @@ expand_manifests(const string &input_expr, bool expand_undefined,
             expand_manifest_inline(expr, q, p, manifest);
             expand_manifest_inline(expr, q, p, manifest);
             manifest_found = true;
             manifest_found = true;
 
 
+          } else if (ident == "__FILE__") {
+            // Special case: this is a dynamic definition.
+            string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\"";
+            expr = expr.substr(0, q) + file + expr.substr(p);
+            p = q + file.size();
+            manifest_found = true;
+
+          } else if (ident == "__LINE__") {
+            // So is this.
+            string line = format_string(loc.first_line);
+            expr = expr.substr(0, q) + line + expr.substr(p);
+            p = q + line.size();
+            manifest_found = true;
+
           } else if (expand_undefined && ident != "true" && ident != "false") {
           } else if (expand_undefined && ident != "true" && ident != "false") {
             // It is not found.  Expand it to 0, but only if we are currently
             // It is not found.  Expand it to 0, but only if we are currently
             // parsing an #if expression.
             // parsing an #if expression.
@@ -951,7 +976,7 @@ internal_get_next_token() {
     case ',':
     case ',':
       if (_paren_nesting <= 0) {
       if (_paren_nesting <= 0) {
         _state = S_end_nested;
         _state = S_end_nested;
-        return CPPToken::eof();
+        return CPPToken(0, loc);
       }
       }
       break;
       break;
 
 
@@ -959,9 +984,16 @@ internal_get_next_token() {
       if (_paren_nesting <= 0) {
       if (_paren_nesting <= 0) {
         _parsing_template_params = false;
         _parsing_template_params = false;
         _state = S_end_nested;
         _state = S_end_nested;
-        return CPPToken::eof();
+        return CPPToken(0, loc);
       }
       }
     }
     }
+  } else if (_parsing_attribute) {
+    // If we're parsing an attribute, also keep track of the paren nesting.
+    if (c == '[' || c == '(') {
+      ++_paren_nesting;
+    } else if (c == ']' || c == ')') {
+      --_paren_nesting;
+    }
   }
   }
 
 
   // Look for an end-of-line comment, and parse it before we finish this
   // Look for an end-of-line comment, and parse it before we finish this
@@ -1066,6 +1098,20 @@ check_digraph(int c) {
     if (next_c == '=') return MODEQUAL;
     if (next_c == '=') return MODEQUAL;
     if (next_c == '>') return '}';
     if (next_c == '>') return '}';
     break;
     break;
+
+  case '[':
+    if (next_c == '[' && !_parsing_attribute) {
+      _parsing_attribute = true;
+      return ATTR_LEFT;
+    }
+    break;
+
+  case ']':
+    if (next_c == ']' && _parsing_attribute && _paren_nesting == 0) {
+      _parsing_attribute = false;
+      return ATTR_RIGHT;
+    }
+    break;
   }
   }
 
 
   return 0;
   return 0;
@@ -1453,7 +1499,6 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
       CPPManifest *other = result.first->second;
       CPPManifest *other = result.first->second;
       warning("redefinition of macro '" + manifest->_name + "'", loc);
       warning("redefinition of macro '" + manifest->_name + "'", loc);
       warning("previous definition is here", other->_loc);
       warning("previous definition is here", other->_loc);
-      delete other;
       result.first->second = manifest;
       result.first->second = manifest;
     }
     }
   }
   }
@@ -1479,14 +1524,10 @@ handle_undef_directive(const string &args, const YYLTYPE &loc) {
  */
  */
 void CPPPreprocessor::
 void CPPPreprocessor::
 handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
 handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
-  Manifests::const_iterator mi = _manifests.find(args);
-  if (mi != _manifests.end()) {
-    // The macro is defined.  We continue.
-    return;
+  if (!is_manifest_defined(args)) {
+    // The macro is undefined.  Skip stuff.
+    skip_false_if_block(true);
   }
   }
-
-  // The macro is undefined.  Skip stuff.
-  skip_false_if_block(true);
 }
 }
 
 
 /**
 /**
@@ -1494,17 +1535,12 @@ handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
  */
  */
 void CPPPreprocessor::
 void CPPPreprocessor::
 handle_ifndef_directive(const string &args, const YYLTYPE &loc) {
 handle_ifndef_directive(const string &args, const YYLTYPE &loc) {
-  Manifests::const_iterator mi = _manifests.find(args);
-  if (mi == _manifests.end()) {
-    // The macro is undefined.  We continue.
-    return;
+  if (is_manifest_defined(args)) {
+    // The macro is defined.  Skip stuff.
+    skip_false_if_block(true);
   }
   }
-
-  // The macro is defined.  Skip stuff.
-  skip_false_if_block(true);
 }
 }
 
 
-
 /**
 /**
  *
  *
  */
  */
@@ -1586,6 +1622,8 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
         _angle_includes.insert(filename);
         _angle_includes.insert(filename);
       }
       }
     }
     }
+  } else {
+    warning("Ignoring invalid #include directive", loc);
   }
   }
 
 
   filename.set_text();
   filename.set_text();
@@ -1593,71 +1631,30 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
 
 
   // Now look for the filename.  If we didn't use angle quotes, look first in
   // Now look for the filename.  If we didn't use angle quotes, look first in
   // the current directory.
   // the current directory.
-  bool found_file = false;
   CPPFile::Source source = CPPFile::S_none;
   CPPFile::Source source = CPPFile::S_none;
 
 
-  if (okflag) {
-    found_file = false;
+  if (find_include(filename, angle_quotes, source)) {
+    _last_c = '\0';
 
 
-    // Search the current directory.
-    if (!angle_quotes && !found_file && filename.exists()) {
-      found_file = true;
+    // If it was explicitly named on the command-line, mark it S_local.
+    filename.make_canonical();
+    if (_explicit_files.count(filename)) {
       source = CPPFile::S_local;
       source = CPPFile::S_local;
     }
     }
 
 
-    // Search the same directory as the includer.
-    if (!angle_quotes && !found_file) {
-      Filename match(get_file()._filename.get_dirname(), filename);
-      if (match.exists()) {
-        filename = match;
-        found_file = true;
-        source = CPPFile::S_alternate;
-      }
-    }
-
-    // Now search the angle-include-path
-    if (angle_quotes && !found_file && filename.resolve_filename(_angle_include_path)) {
-      found_file = true;
-      source = CPPFile::S_system;
-    }
+    CPPFile file(filename, filename_as_referenced, source);
 
 
-    // Now search the quote-include-path
-    if (!angle_quotes && !found_file) {
-      for (size_t dir=0; dir<_quote_include_path.get_num_directories(); dir++) {
-        Filename match(_quote_include_path.get_directory(dir), filename);
-        if (match.exists()) {
-          filename = match;
-          found_file = true;
-          source = _quote_include_kind[dir];
-        }
-      }
+    // Don't include it if we included it before and it had #pragma once.
+    ParsedFiles::const_iterator it = _parsed_files.find(file);
+    if (it != _parsed_files.end() && it->_pragma_once) {
+      return;
     }
     }
 
 
-    if (!found_file) {
-      warning("Cannot find " + filename.get_fullpath(), loc);
-    } else {
-      _last_c = '\0';
-
-      // If it was explicitly named on the command-line, mark it S_local.
-      filename.make_absolute();
-      if (_explicit_files.count(filename)) {
-        source = CPPFile::S_local;
-      }
-
-      CPPFile file(filename, filename_as_referenced, source);
-
-      // Don't include it if we included it before and it had #pragma once.
-      ParsedFiles::const_iterator it = _parsed_files.find(file);
-      if (it != _parsed_files.end() && it->_pragma_once) {
-        return;
-      }
-
-      if (!push_file(file)) {
-        warning("Unable to read " + filename.get_fullpath(), loc);
-      }
+    if (!push_file(file)) {
+      warning("Unable to read " + filename.get_fullpath(), loc);
     }
     }
   } else {
   } else {
-    warning("Ignoring invalid #include directive", loc);
+    warning("Cannot find " + filename.get_fullpath(), loc);
   }
   }
 }
 }
 
 
@@ -1671,6 +1668,38 @@ handle_pragma_directive(const string &args, const YYLTYPE &loc) {
     assert(it != _parsed_files.end());
     assert(it != _parsed_files.end());
     it->_pragma_once = true;
     it->_pragma_once = true;
   }
   }
+
+  char macro[64];
+  if (sscanf(args.c_str(), "push_macro ( \"%63[^\"]\" )", macro) == 1) {
+    // We just mark it as pushed for now, so that the next time someone tries
+    // to override it, we save the old value.
+    Manifests::iterator mi = _manifests.find(macro);
+    if (mi != _manifests.end()) {
+      _manifest_stack[macro].push_back(mi->second);
+    } else {
+      _manifest_stack[macro].push_back(NULL);
+    }
+
+  } else if (sscanf(args.c_str(), "pop_macro ( \"%63[^\"]\" )", macro) == 1) {
+    ManifestStack &stack = _manifest_stack[macro];
+    if (stack.size() > 0) {
+      CPPManifest *manifest = stack.back();
+      stack.pop_back();
+      Manifests::iterator mi = _manifests.find(macro);
+      if (manifest == NULL) {
+        // It was undefined when it was pushed, so make it undefined again.
+        if (mi != _manifests.end()) {
+          _manifests.erase(mi);
+        }
+      } else if (mi != _manifests.end()) {
+        mi->second = manifest;
+      } else {
+        _manifests.insert(Manifests::value_type(macro, manifest));
+      }
+    } else {
+      warning("pop_macro without matching push_macro", loc);
+    }
+  }
 }
 }
 
 
 /**
 /**
@@ -1740,6 +1769,69 @@ skip_false_if_block(bool consider_elifs) {
   _save_comments = true;
   _save_comments = true;
 }
 }
 
 
+/**
+ * Returns true if the given manifest is defined.
+ */
+bool CPPPreprocessor::
+is_manifest_defined(const string &manifest_name) {
+  Manifests::const_iterator mi = _manifests.find(manifest_name);
+  if (mi != _manifests.end()) {
+    return true;
+  }
+
+  if (manifest_name == "__has_include" ||
+      manifest_name == "__FILE__" ||
+      manifest_name == "__LINE__") {
+    // Special built-in directives that are considered "defined".
+    return true;
+  }
+
+  return false;
+}
+
+/**
+ * Locates the given filename.  Changes the first argument to the full path.
+ */
+bool CPPPreprocessor::
+find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) {
+  // Now look for the filename.  If we didn't use angle quotes, look first in
+  // the current directory.
+  if (!angle_quotes && filename.exists()) {
+    source = CPPFile::S_local;
+    return true;
+  }
+
+  // Search the same directory as the includer.
+  if (!angle_quotes) {
+    Filename match(get_file()._filename.get_dirname(), filename);
+    if (match.exists()) {
+      filename = match;
+      source = CPPFile::S_alternate;
+      return true;
+    }
+  }
+
+  // Now search the angle-include-path
+  if (angle_quotes && filename.resolve_filename(_angle_include_path)) {
+    source = CPPFile::S_system;
+    return true;
+  }
+
+  // Now search the quote-include-path
+  if (!angle_quotes) {
+    for (size_t dir = 0; dir < _quote_include_path.get_num_directories(); ++dir) {
+      Filename match(_quote_include_path.get_directory(dir), filename);
+      if (match.exists()) {
+        filename = match;
+        source = _quote_include_kind[dir];
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -1800,11 +1892,19 @@ get_identifier(int c) {
   loc.last_column = get_col_number();
   loc.last_column = get_col_number();
 
 
   if ((c == '\'' || c == '"') &&
   if ((c == '\'' || c == '"') &&
-      (name == "L" || name == "u8" ||
-       name == "u" || name == "U")) {
+      (name == "L" || name == "u8" || name == "u" || name == "U" ||
+       name == "R" || name == "LR" || name == "u8R" || name == "uR" || name == "UR")) {
     // This is actually a wide-character or wide-string literal or some such.
     // This is actually a wide-character or wide-string literal or some such.
-    // Figure out the correct character type to use.
+    get();
+    string str;
+    if (name[name.size() - 1] == 'R') {
+      name.resize(name.size() - 1);
+      str = scan_raw(c);
+    } else {
+      str = scan_quoted(c);
+    }
 
 
+    // Figure out the correct character type to use.
     CPPExpression::Type type;
     CPPExpression::Type type;
     if (name == "L") {
     if (name == "L") {
       type = CPPExpression::T_wstring;
       type = CPPExpression::T_wstring;
@@ -1817,8 +1917,6 @@ get_identifier(int c) {
     } else {
     } else {
       type = CPPExpression::T_string;
       type = CPPExpression::T_string;
     }
     }
-    get();
-    string str = scan_quoted(c);
 
 
     loc.last_line = get_line_number();
     loc.last_line = get_line_number();
     loc.last_column = get_col_number();
     loc.last_column = get_col_number();
@@ -1846,6 +1944,14 @@ get_identifier(int c) {
   if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
   if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
     return expand_manifest((*mi).second);
     return expand_manifest((*mi).second);
   }
   }
+  if (name == "__FILE__") {
+    return get_literal(SIMPLE_STRING, loc, loc.file._filename_as_referenced);
+  }
+  if (name == "__LINE__") {
+    YYSTYPE result;
+    result.u.integer = loc.first_line;
+    return CPPToken(INTEGER, loc, "", result);
+  }
 
 
   // Check for keywords.
   // Check for keywords.
   int kw = check_keyword(name);
   int kw = check_keyword(name);
@@ -2188,9 +2294,7 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
   vector_string args;
   vector_string args;
   extract_manifest_args_inline("defined", 1, -1, args, expr, p);
   extract_manifest_args_inline("defined", 1, -1, args, expr, p);
   if (args.size() >= 1) {
   if (args.size() >= 1) {
-    const string &manifest_name = args[0];
-    Manifests::const_iterator mi = _manifests.find(manifest_name);
-    if (mi != _manifests.end()) {
+    if (is_manifest_defined(args[0])) {
       // The macro is defined; the result is "1".
       // The macro is defined; the result is "1".
       result = "1";
       result = "1";
     } else {
     } else {
@@ -2203,6 +2307,70 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
   p = q + result.size();
   p = q + result.size();
 }
 }
 
 
+/**
+ * Expands the __has_include(manifest) function to either 1 or 0, depending on
+ * whether the include file exists.
+ */
+void CPPPreprocessor::
+expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc) {
+  bool found_file = false;
+
+  // Skip whitespace till paren.
+  while (p < expr.size() && isspace(expr[p])) {
+    p++;
+  }
+  size_t args_begin = p + 1;
+
+  vector_string args;
+  extract_manifest_args_inline("__has_include", 1, -1, args, expr, p);
+
+  if (!args.empty() && args[0].size() >= 2) {
+    Filename filename;
+    bool angle_quotes = false;
+
+    string inc = args[0];
+
+    // Just to play things safe, since our manifest-expansion logic might not
+    // filter out quotes and angle brackets properly, we'll only expand
+    // manifests if we don't begin with a quote or bracket.
+    if (!inc.empty() && (inc[0] != '"' && inc[0] != '<')) {
+      inc = expand_manifests(inc, false, loc);
+    }
+
+    if (inc[0] == '"' && inc[inc.size() - 1] == '"') {
+      filename = inc.substr(1, inc.size() - 2);
+    } else if (inc[0] == '<' && inc[inc.size() - 1] == '>') {
+      filename = inc.substr(1, inc.size() - 2);
+      if (!_noangles) {
+        // If _noangles is true, we don't make a distinction between angle
+        // brackets and quote marks--all #inc statements are treated the
+        // same, as if they used quote marks.
+        angle_quotes = true;
+      }
+    } else {
+      loc.last_column += loc.first_column + p - 2;
+      loc.first_column += args_begin;
+      warning("invalid argument for __has_include() directive", loc);
+      expr = expr.substr(0, q) + "0" + expr.substr(p);
+      p = q + 1;
+      return;
+    }
+
+    filename.set_text();
+
+    CPPFile::Source source = CPPFile::S_none;
+    found_file = find_include(filename, angle_quotes, source);
+  } else {
+    loc.last_column += loc.first_column + p - 2;
+    loc.first_column += args_begin;
+    warning("invalid argument for __has_include() directive", loc);
+  }
+
+  string result = found_file ? "1" : "0";
+  expr = expr.substr(0, q) + result + expr.substr(p);
+  p = q + result.size();
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -2451,11 +2619,27 @@ check_keyword(const string &name) {
   if (name == "friend") return KW_FRIEND;
   if (name == "friend") return KW_FRIEND;
   if (name == "for") return KW_FOR;
   if (name == "for") return KW_FOR;
   if (name == "goto") return KW_GOTO;
   if (name == "goto") return KW_GOTO;
+  if (name == "__has_virtual_destructor") return KW_HAS_VIRTUAL_DESTRUCTOR;
   if (name == "if") return KW_IF;
   if (name == "if") return KW_IF;
   if (name == "inline") return KW_INLINE;
   if (name == "inline") return KW_INLINE;
   if (name == "__inline") return KW_INLINE;
   if (name == "__inline") return KW_INLINE;
   if (name == "__inline__") return KW_INLINE;
   if (name == "__inline__") return KW_INLINE;
   if (name == "int") return KW_INT;
   if (name == "int") return KW_INT;
+  if (name == "__is_abstract") return KW_IS_ABSTRACT;
+  if (name == "__is_base_of") return KW_IS_BASE_OF;
+  if (name == "__is_class") return KW_IS_CLASS;
+  if (name == "__is_constructible") return KW_IS_CONSTRUCTIBLE;
+  if (name == "__is_convertible_to") return KW_IS_CONVERTIBLE_TO;
+  if (name == "__is_destructible") return KW_IS_DESTRUCTIBLE;
+  if (name == "__is_empty") return KW_IS_EMPTY;
+  if (name == "__is_enum") return KW_IS_ENUM;
+  if (name == "__is_final") return KW_IS_FINAL;
+  if (name == "__is_fundamental") return KW_IS_FUNDAMENTAL;
+  if (name == "__is_pod") return KW_IS_POD;
+  if (name == "__is_polymorphic") return KW_IS_POLYMORPHIC;
+  if (name == "__is_standard_layout") return KW_IS_STANDARD_LAYOUT;
+  if (name == "__is_trivial") return KW_IS_TRIVIAL;
+  if (name == "__is_union") return KW_IS_UNION;
   if (name == "long") return KW_LONG;
   if (name == "long") return KW_LONG;
   if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY;
   if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY;
   if (name == "__make_property") return KW_MAKE_PROPERTY;
   if (name == "__make_property") return KW_MAKE_PROPERTY;
@@ -2490,6 +2674,7 @@ check_keyword(const string &name) {
   if (name == "typedef") return KW_TYPEDEF;
   if (name == "typedef") return KW_TYPEDEF;
   if (name == "typeid") return KW_TYPEID;
   if (name == "typeid") return KW_TYPEID;
   if (name == "typename") return KW_TYPENAME;
   if (name == "typename") return KW_TYPENAME;
+  if (name == "__underlying_type") return KW_UNDERLYING_TYPE;
   if (name == "union") return KW_UNION;
   if (name == "union") return KW_UNION;
   if (name == "unsigned") return KW_UNSIGNED;
   if (name == "unsigned") return KW_UNSIGNED;
   if (name == "using") return KW_USING;
   if (name == "using") return KW_USING;
@@ -2615,6 +2800,43 @@ scan_quoted(int c) {
   return str;
   return str;
 }
 }
 
 
+/**
+ * Parses a C++11 raw string.
+ */
+string CPPPreprocessor::
+scan_raw(int c) {
+  int quote_mark = c;
+
+  string delimiter = ")";
+
+  string str;
+  c = get();
+  while (c != EOF && c != '(') {
+    delimiter += c;
+    c = get();
+  }
+
+  // OK, now start parsing the string, until we see the delimiter again.
+  c = get();
+  while (c != EOF) {
+    if (c == quote_mark) {
+      // We encountered a quote mark - did the last part of the string end
+      // with the given delimiter?  If so, we've reached the end.
+      if (str.compare(str.size() - delimiter.size(), delimiter.size(), delimiter) == 0) {
+        str.resize(str.size() - delimiter.size());
+        break;
+      }
+    }
+    str += c;
+    c = get();
+  }
+
+  if (c != quote_mark) {
+    warning("Unclosed string");
+  }
+  return str;
+}
+
 /**
 /**
  * Returns true if the manifest is one that is being ignored right now
  * Returns true if the manifest is one that is being ignored right now
  * (presumably because we are presently expanding it).
  * (presumably because we are presently expanding it).
@@ -2751,7 +2973,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
   _parsing_template_params = true;
   _parsing_template_params = true;
 
 
   CPPToken token = internal_get_next_token();
   CPPToken token = internal_get_next_token();
-  if (token._token == '>') {
+  if (token._token == '>' || token._token == 0) {
     _parsing_template_params = false;
     _parsing_template_params = false;
   } else {
   } else {
     _saved_tokens.push_back(token);
     _saved_tokens.push_back(token);
@@ -2760,36 +2982,53 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
   CPPTemplateParameterList *actual_params = new CPPTemplateParameterList;
   CPPTemplateParameterList *actual_params = new CPPTemplateParameterList;
 
 
   for (pi = formal_params._parameters.begin();
   for (pi = formal_params._parameters.begin();
-       pi != formal_params._parameters.end() && _parsing_template_params;
-       ++pi) {
+       pi != formal_params._parameters.end() && _parsing_template_params;) {
     CPPToken token = peek_next_token();
     CPPToken token = peek_next_token();
     YYLTYPE loc = token._lloc;
     YYLTYPE loc = token._lloc;
 
 
     CPPDeclaration *decl = (*pi);
     CPPDeclaration *decl = (*pi);
-    if (decl->as_type()) {
+    CPPClassTemplateParameter *param = decl->as_class_template_parameter();
+    CPPInstance *inst = decl->as_instance();
+    if (param) {
       // Parse a typename template parameter.
       // Parse a typename template parameter.
       _saved_tokens.push_back(CPPToken(START_TYPE));
       _saved_tokens.push_back(CPPToken(START_TYPE));
       CPPType *type = ::parse_type(this, current_scope, global_scope);
       CPPType *type = ::parse_type(this, current_scope, global_scope);
       if (type == NULL) {
       if (type == NULL) {
         loc.last_line = get_line_number();
         loc.last_line = get_line_number();
         loc.last_column = get_col_number() - 1;
         loc.last_column = get_col_number() - 1;
-        warning("Invalid type", loc);
+        warning("invalid type", loc);
         skip_to_end_nested();
         skip_to_end_nested();
         type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
         type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
       }
       }
       actual_params->_parameters.push_back(type);
       actual_params->_parameters.push_back(type);
-    } else {
+
+      // If this is a variadic template, keep reading using this parameter.
+      if (!param->_packed) {
+        ++pi;
+      }
+    } else if (inst) {
       // Parse a constant expression template parameter.
       // Parse a constant expression template parameter.
       _saved_tokens.push_back(CPPToken(START_CONST_EXPR));
       _saved_tokens.push_back(CPPToken(START_CONST_EXPR));
       CPPExpression *expr = parse_const_expr(this, current_scope, global_scope);
       CPPExpression *expr = parse_const_expr(this, current_scope, global_scope);
       if (expr == NULL) {
       if (expr == NULL) {
         loc.last_line = get_line_number();
         loc.last_line = get_line_number();
         loc.last_column = get_col_number() - 1;
         loc.last_column = get_col_number() - 1;
-        warning("Invalid expression", loc);
+        warning("invalid expression", loc);
         skip_to_end_nested();
         skip_to_end_nested();
         expr = new CPPExpression(0);
         expr = new CPPExpression(0);
       }
       }
       actual_params->_parameters.push_back(expr);
       actual_params->_parameters.push_back(expr);
+
+      // If this is a variadic template, keep reading using this parameter.
+      if ((inst->_storage_class & CPPInstance::SC_parameter_pack) == 0) {
+        ++pi;
+      }
+    } else {
+      loc.last_line = get_line_number();
+      loc.last_column = get_col_number() - 1;
+      warning("invalid template parameter", loc);
+      skip_to_end_nested();
+      ++pi;
     }
     }
 
 
     _state = S_nested;
     _state = S_nested;

+ 8 - 0
dtool/src/cppparser/cppPreprocessor.h

@@ -72,6 +72,9 @@ public:
   typedef map<string, CPPManifest *> Manifests;
   typedef map<string, CPPManifest *> Manifests;
   Manifests _manifests;
   Manifests _manifests;
 
 
+  typedef pvector<CPPManifest *> ManifestStack;
+  map<string, ManifestStack> _manifest_stack;
+
   pvector<CPPFile::Source> _quote_include_kind;
   pvector<CPPFile::Source> _quote_include_kind;
   DSearchPath _quote_include_path;
   DSearchPath _quote_include_path;
   DSearchPath _angle_include_path;
   DSearchPath _angle_include_path;
@@ -140,6 +143,8 @@ private:
   void handle_error_directive(const string &args, const YYLTYPE &loc);
   void handle_error_directive(const string &args, const YYLTYPE &loc);
 
 
   void skip_false_if_block(bool consider_elifs);
   void skip_false_if_block(bool consider_elifs);
+  bool is_manifest_defined(const string &manifest_name);
+  bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source);
 
 
   CPPToken get_quoted_char(int c);
   CPPToken get_quoted_char(int c);
   CPPToken get_quoted_string(int c);
   CPPToken get_quoted_string(int c);
@@ -150,6 +155,7 @@ private:
   void extract_manifest_args(const string &name, int num_args,
   void extract_manifest_args(const string &name, int num_args,
                              int va_arg, vector_string &args);
                              int va_arg, vector_string &args);
   void expand_defined_function(string &expr, size_t q, size_t &p);
   void expand_defined_function(string &expr, size_t q, size_t &p);
+  void expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc);
   void expand_manifest_inline(string &expr, size_t q, size_t &p,
   void expand_manifest_inline(string &expr, size_t q, size_t &p,
                               const CPPManifest *manifest);
                               const CPPManifest *manifest);
   void extract_manifest_args_inline(const string &name, int num_args,
   void extract_manifest_args_inline(const string &name, int num_args,
@@ -160,6 +166,7 @@ private:
   static int check_keyword(const string &name);
   static int check_keyword(const string &name);
   int scan_escape_sequence(int c);
   int scan_escape_sequence(int c);
   string scan_quoted(int c);
   string scan_quoted(int c);
+  string scan_raw(int c);
 
 
   bool should_ignore_manifest(const CPPManifest *manifest) const;
   bool should_ignore_manifest(const CPPManifest *manifest) const;
   bool should_ignore_preprocessor() const;
   bool should_ignore_preprocessor() const;
@@ -206,6 +213,7 @@ private:
   State _state;
   State _state;
   int _paren_nesting;
   int _paren_nesting;
   bool _parsing_template_params;
   bool _parsing_template_params;
+  bool _parsing_attribute;
 
 
   bool _start_of_line;
   bool _start_of_line;
   int _unget;
   int _unget;

+ 79 - 0
dtool/src/cppparser/cppReferenceType.cxx

@@ -12,6 +12,8 @@
  */
  */
 
 
 #include "cppReferenceType.h"
 #include "cppReferenceType.h"
+#include "cppTypedefType.h"
+#include "cppStructType.h"
 
 
 /**
 /**
  *
  *
@@ -87,6 +89,14 @@ is_tbd() const {
   return _pointing_at->is_tbd();
   return _pointing_at->is_tbd();
 }
 }
 
 
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPReferenceType::
+is_standard_layout() const {
+  return false;
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -95,6 +105,67 @@ is_trivial() const {
   return false;
   return false;
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPReferenceType::
+is_constructible(const CPPType *given_type) const {
+  const CPPType *a;
+  const CPPType *b;
+
+  CPPReferenceType *ref_type = ((CPPType *)given_type)->as_reference_type();
+  if (ref_type != NULL) {
+    if (ref_type->_value_category == VC_rvalue) {
+      return is_constructible(ref_type->_pointing_at);
+    }
+
+    if (_value_category == VC_rvalue) {
+      // Can never initialize an rvalue ref from an lvalue ref.
+      return false;
+    }
+
+    if (!_pointing_at->is_const()) {
+      // Cannot initialize a non-const reference using a const one.
+      if (ref_type->_pointing_at->is_const()) {
+        return false;
+      }
+    }
+
+    a = _pointing_at->remove_cv();
+    b = ref_type->_pointing_at->remove_cv();
+
+  } else {
+    // Initializing using an rvalue.
+    if (!_pointing_at->is_const()) {
+      // Cannot initialize a non-const reference using a const one.
+      if (given_type->is_const()) {
+        return false;
+      }
+
+      // Cannot initalise a non-const lvalue reference with an rvalue ref.
+      if (_value_category == VC_lvalue) {
+        return false;
+      }
+    }
+
+    a = _pointing_at->remove_cv();
+    b = ((CPPType *)given_type)->remove_cv();
+  }
+
+  if (a == b || *a == *b) {
+    return true;
+  }
+
+  // Can initialize from derived class pointer.
+  const CPPStructType *a_struct = a->as_struct_type();
+  const CPPStructType *b_struct = b->as_struct_type();
+  if (a_struct != NULL && b_struct != NULL) {
+    return a_struct->is_base_of(b_struct);
+  }
+
+  return false;
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
@@ -111,6 +182,14 @@ is_copy_constructible() const {
   return (_value_category == VC_lvalue);
   return (_value_category == VC_lvalue);
 }
 }
 
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPReferenceType::
+is_destructible() const {
+  return false;
+}
+
 /**
 /**
  * This is a little more forgiving than is_equal(): it returns true if the
  * This is a little more forgiving than is_equal(): it returns true if the
  * types appear to be referring to the same thing, even if they may have
  * types appear to be referring to the same thing, even if they may have

+ 3 - 0
dtool/src/cppparser/cppReferenceType.h

@@ -42,9 +42,12 @@ public:
                                 CPPScope *global_scope);
                                 CPPScope *global_scope);
 
 
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
   virtual bool is_equivalent(const CPPType &other) const;
   virtual bool is_equivalent(const CPPType &other) const;
 
 
   virtual void output(ostream &out, int indent_level, CPPScope *scope,
   virtual void output(ostream &out, int indent_level, CPPScope *scope,

+ 1 - 1
dtool/src/cppparser/cppScope.cxx

@@ -27,8 +27,8 @@
 #include "cppPreprocessor.h"
 #include "cppPreprocessor.h"
 #include "cppTemplateScope.h"
 #include "cppTemplateScope.h"
 #include "cppClassTemplateParameter.h"
 #include "cppClassTemplateParameter.h"
-#include "cppConstType.h"
 #include "cppFunctionType.h"
 #include "cppFunctionType.h"
+#include "cppConstType.h"
 #include "cppUsing.h"
 #include "cppUsing.h"
 #include "cppBisonDefs.h"
 #include "cppBisonDefs.h"
 #include "indent.h"
 #include "indent.h"

+ 3 - 2
dtool/src/cppparser/cppScope.h

@@ -139,11 +139,12 @@ public:
   Templates _templates;
   Templates _templates;
   CPPNameComponent _name;
   CPPNameComponent _name;
 
 
+  typedef set<CPPScope *> Using;
+  Using _using;
+
 protected:
 protected:
   CPPScope *_parent_scope;
   CPPScope *_parent_scope;
   CPPStructType *_struct_type;
   CPPStructType *_struct_type;
-  typedef set<CPPScope *> Using;
-  Using _using;
   CPPVisibility _current_vis;
   CPPVisibility _current_vis;
 
 
 private:
 private:

+ 53 - 0
dtool/src/cppparser/cppSimpleType.cxx

@@ -34,6 +34,30 @@ is_tbd() const {
   return (_type == T_unknown);
   return (_type == T_unknown);
 }
 }
 
 
+/**
+ * Returns true if the type is a boolean, floating point or integral type.
+ */
+bool CPPSimpleType::
+is_arithmetic() const {
+  return (_type > T_unknown && _type < T_void);
+}
+
+/**
+ * Returns true if the type is considered a fundamental type.
+ */
+bool CPPSimpleType::
+is_fundamental() const {
+  return (_type != T_unknown && _type != T_parameter && _type != T_auto);
+}
+
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPSimpleType::
+is_standard_layout() const {
+  return (_type != T_unknown && _type != T_parameter && _type != T_auto);
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -42,6 +66,27 @@ is_trivial() const {
   return true;
   return true;
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPSimpleType::
+is_constructible(const CPPType *given_type) const {
+  given_type = ((CPPType *)given_type)->remove_reference()->remove_cv();
+
+  const CPPSimpleType *simple_type = given_type->as_simple_type();
+  if (simple_type == NULL) {
+    return given_type->is_enum() && is_arithmetic();
+  } else if (_type == T_nullptr) {
+    return simple_type->_type == T_nullptr;
+  } else if (_type == T_bool) {
+    return simple_type->is_arithmetic() || simple_type->_type == T_nullptr;
+  } else if (is_arithmetic()) {
+    return simple_type->is_arithmetic();
+  } else {
+    return false;
+  }
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
@@ -58,6 +103,14 @@ is_copy_constructible() const {
   return (_type != T_void);
   return (_type != T_void);
 }
 }
 
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPSimpleType::
+is_destructible() const {
+  return (_type != T_void);
+}
+
 /**
 /**
  * Returns true if the type is a special parameter expression type.
  * Returns true if the type is a special parameter expression type.
  *
  *

+ 11 - 7
dtool/src/cppparser/cppSimpleType.h

@@ -19,7 +19,7 @@
 #include "cppType.h"
 #include "cppType.h"
 
 
 /**
 /**
- *
+ * Represents a C++ fundamental type.
  */
  */
 class CPPSimpleType : public CPPType {
 class CPPSimpleType : public CPPType {
 public:
 public:
@@ -40,12 +40,11 @@ public:
     // nullptr_t, which is a typedef of decltype(nullptr).
     // nullptr_t, which is a typedef of decltype(nullptr).
     T_nullptr,
     T_nullptr,
 
 
-/*
- * T_parameter is a special type which is assigned to expressions that are
- * discovered where a formal parameter was expected.  This is a special case
- * for handling cases like this: int foo(0); which really means the same thing
- * as: int foo = 0; but it initially looks like a function prototype.
- */
+    // T_parameter is a special type which is assigned to expressions that are
+    // discovered where a formal parameter was expected.  This is a special
+    // case for handling cases like this: int foo(0); which really means the
+    // same thing as: int foo = 0; but it initially looks like a function
+    // prototype.
     T_parameter,
     T_parameter,
 
 
     // T_auto is also a special type that corresponds to the "auto" keyword
     // T_auto is also a special type that corresponds to the "auto" keyword
@@ -69,9 +68,14 @@ public:
   int _flags;
   int _flags;
 
 
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  bool is_arithmetic() const;
+  virtual bool is_fundamental() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
   virtual bool is_parameter_expr() const;
   virtual bool is_parameter_expr() const;
 
 
   virtual string get_preferred_name() const;
   virtual string get_preferred_name() const;

+ 379 - 39
dtool/src/cppparser/cppStructType.cxx

@@ -13,6 +13,7 @@
 
 
 #include "cppStructType.h"
 #include "cppStructType.h"
 #include "cppTypedefType.h"
 #include "cppTypedefType.h"
+#include "cppReferenceType.h"
 #include "cppScope.h"
 #include "cppScope.h"
 #include "cppTypeProxy.h"
 #include "cppTypeProxy.h"
 #include "cppTemplateScope.h"
 #include "cppTemplateScope.h"
@@ -126,16 +127,154 @@ is_abstract() const {
   return !funcs.empty();
   return !funcs.empty();
 }
 }
 
 
+/**
+ * Returns true if this struct declaration is a base class of the other given
+ * class, or the same class.
+ */
+bool CPPStructType::
+is_base_of(const CPPStructType *other) const {
+  if (this == other) {
+    return true;
+  }
+  Derivation::const_iterator di;
+  for (di = other->_derivation.begin(); di != other->_derivation.end(); ++di) {
+    const CPPStructType *base = (*di)._base->as_struct_type();
+    if (base != NULL && is_base_of(base)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Returns true if this struct declaration defines no non-static data members
+ * other than bit-fields of size 0, no virtual functions, no virtual base
+ * classes, and no non-empty base classes, and is not a union.
+ */
+bool CPPStructType::
+is_empty() const {
+  if (_type == T_union) {
+    return false;
+  }
+
+  if (check_virtual()) {
+    return false;
+  }
+
+  // Make sure all base classes are empty and non-virtual.
+  Derivation::const_iterator di;
+  for (di = _derivation.begin(); di != _derivation.end(); ++di) {
+    CPPStructType *base = (*di)._base->as_struct_type();
+    if ((*di)._is_virtual || (base != NULL && !base->is_empty())) {
+      return false;
+    }
+  }
+
+  // Make sure there are no non-static data members.
+  CPPScope::Variables::const_iterator vi;
+  for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
+    CPPInstance *instance = (*vi).second;
+    assert(instance != NULL);
+
+    if (instance->_storage_class & CPPInstance::SC_static) {
+      // Static members don't count.
+      continue;
+    }
+
+    // Only members with a bit width of 0 are okay.
+    if (instance->_bit_width != 0) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+/**
+ * Returns true if this class or any of its base classes have virtual methods.
+ */
+bool CPPStructType::
+is_polymorphic() const {
+  if (_type == T_union) {
+    return false;
+  }
+  return check_virtual();
+}
+
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPStructType::
+is_standard_layout() const {
+  assert(_scope != NULL);
+
+  CPPVisibility member_vis = V_unknown;
+
+  // Make sure all data members have the same vis and are standard layout.
+  CPPScope::Variables::const_iterator vi;
+  for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
+    CPPInstance *instance = (*vi).second;
+    assert(instance != NULL);
+
+    if (instance->_storage_class & CPPInstance::SC_static) {
+      // Static members don't count.
+      continue;
+    }
+
+    // Finally, check if the data member itself is standard layout.
+    assert(instance->_type != NULL);
+    if (!instance->_type->is_standard_layout()) {
+      return false;
+    }
+
+    if (member_vis == V_unknown) {
+      // The first non-static data member may not be a base class.
+      CPPStructType *struct_type = instance->_type->remove_cv()->as_struct_type();
+      if (struct_type != NULL && struct_type->is_base_of(this)) {
+        return false;
+      }
+      member_vis = instance->_vis;
+
+    } else if (member_vis != instance->_vis) {
+      // All members need to have the same access control.
+      return false;
+    }
+  }
+
+  // Make sure all base classes are standard-layout and non-virtual.
+  Derivation::const_iterator di;
+  for (di = _derivation.begin(); di != _derivation.end(); ++di) {
+    CPPStructType *base = (*di)._base->as_struct_type();
+    if ((*di)._is_virtual) {
+      return false;
+    }
+
+    // If this class had instance members, all base classes need to be empty.
+    if (member_vis != V_unknown) {
+      if (!base->is_empty()) {
+        return false;
+      }
+    } else {
+      if (!base->is_standard_layout()) {
+        return false;
+      }
+    }
+  }
+
+  // Make sure we have no virtual functions.
+  return !check_virtual();
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
 bool CPPStructType::
 bool CPPStructType::
 is_trivial() const {
 is_trivial() const {
-  // Make sure all base classes are trivial.
+  // Make sure all base classes are trivial and non-virtual.
   Derivation::const_iterator di;
   Derivation::const_iterator di;
   for (di = _derivation.begin(); di != _derivation.end(); ++di) {
   for (di = _derivation.begin(); di != _derivation.end(); ++di) {
     CPPStructType *base = (*di)._base->as_struct_type();
     CPPStructType *base = (*di)._base->as_struct_type();
-    if (base != NULL && !base->is_trivial()) {
+    if ((*di)._is_virtual || (base != NULL && !base->is_trivial())) {
       return false;
       return false;
     }
     }
   }
   }
@@ -166,7 +305,7 @@ is_trivial() const {
     }
     }
   }
   }
 
 
-  // Now look for functions that are virtual or condestructors.
+  // Now look for functions that are virtual or con/destructors.
   bool is_default_constructible = true;
   bool is_default_constructible = true;
   CPPScope::Functions::const_iterator fi;
   CPPScope::Functions::const_iterator fi;
   for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
   for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
@@ -193,8 +332,8 @@ is_trivial() const {
       if (ftype->_flags & (CPPFunctionType::F_destructor |
       if (ftype->_flags & (CPPFunctionType::F_destructor |
                            CPPFunctionType::F_move_constructor |
                            CPPFunctionType::F_move_constructor |
                            CPPFunctionType::F_copy_constructor)) {
                            CPPFunctionType::F_copy_constructor)) {
-        // User-provided destructors and copymove constructors are not trivial
-        // unless they are defaulted (and not virtual).
+        // User-provided destructors and copy/move constructors are not
+        // trivial unless they are defaulted (and not virtual).
         return false;
         return false;
       }
       }
 
 
@@ -220,6 +359,66 @@ is_trivial() const {
   return is_default_constructible;
   return is_default_constructible;
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ * This implementation is rudimentary, as it does not attempt to follow all of
+ * the implicit type conversion rules, but it is still useful.
+ */
+bool CPPStructType::
+is_constructible(const CPPType *given_type) const {
+  // Does the type match the copy constructor or move constructor?
+  CPPType *base_type = ((CPPType *)given_type)->remove_reference();
+  if (is_equivalent(*base_type->remove_cv())) {
+    const CPPReferenceType *ref_type = given_type->as_reference_type();
+    if (ref_type == NULL ||
+        ref_type->_value_category == CPPReferenceType::VC_rvalue) {
+      return is_move_constructible(V_public);
+    } else {
+      return is_copy_constructible(V_public);
+    }
+  }
+
+  if (is_abstract()) {
+    return false;
+  }
+
+  // Check for a different constructor.
+  CPPFunctionGroup *fgroup = get_constructor();
+  if (fgroup != (CPPFunctionGroup *)NULL) {
+    CPPFunctionGroup::Instances::const_iterator ii;
+    for (ii = fgroup->_instances.begin();
+        ii != fgroup->_instances.end();
+        ++ii) {
+      CPPInstance *inst = (*ii);
+      assert(inst->_type != (CPPType *)NULL);
+
+      CPPFunctionType *ftype = inst->_type->as_function_type();
+      assert(ftype != (CPPFunctionType *)NULL);
+
+      CPPParameterList *params = ftype->_parameters;
+      if (params->_parameters.size() == 1 && !params->_includes_ellipsis) {
+        CPPType *param_type = params->_parameters[0]->_type->remove_reference();
+
+        if (!param_type->is_const() && base_type->is_const()) {
+          // Can't pass a const object to a function taking a non-const.
+          continue;
+        }
+
+        // It's deleted, anyhow.
+        if ((inst->_storage_class & CPPInstance::SC_deleted) != 0) {
+          continue;
+        }
+
+        if (param_type->is_equivalent(*base_type)) {
+          return true;
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
@@ -236,11 +435,23 @@ is_copy_constructible() const {
   return is_copy_constructible(V_public);
   return is_copy_constructible(V_public);
 }
 }
 
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPStructType::
+is_destructible() const {
+  return is_destructible(V_public);
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
 bool CPPStructType::
 bool CPPStructType::
 is_default_constructible(CPPVisibility min_vis) const {
 is_default_constructible(CPPVisibility min_vis) const {
+  if (is_abstract()) {
+    return false;
+  }
+
   CPPInstance *constructor = get_default_constructor();
   CPPInstance *constructor = get_default_constructor();
   if (constructor != (CPPInstance *)NULL) {
   if (constructor != (CPPInstance *)NULL) {
     // It has a default constructor.
     // It has a default constructor.
@@ -295,24 +506,6 @@ is_default_constructible(CPPVisibility min_vis) const {
     }
     }
   }
   }
 
 
-  // Check that we don't have pure virtual methods.
-  CPPScope::Functions::const_iterator fi;
-  for (fi = _scope->_functions.begin();
-       fi != _scope->_functions.end();
-       ++fi) {
-    CPPFunctionGroup *fgroup = (*fi).second;
-    CPPFunctionGroup::Instances::const_iterator ii;
-    for (ii = fgroup->_instances.begin();
-         ii != fgroup->_instances.end();
-         ++ii) {
-      CPPInstance *inst = (*ii);
-      if (inst->_storage_class & CPPInstance::SC_pure_virtual) {
-        // Here's a pure virtual function.
-        return false;
-      }
-    }
-  }
-
   return true;
   return true;
 }
 }
 
 
@@ -321,6 +514,10 @@ is_default_constructible(CPPVisibility min_vis) const {
  */
  */
 bool CPPStructType::
 bool CPPStructType::
 is_copy_constructible(CPPVisibility min_vis) const {
 is_copy_constructible(CPPVisibility min_vis) const {
+  if (is_abstract()) {
+    return false;
+  }
+
   CPPInstance *constructor = get_copy_constructor();
   CPPInstance *constructor = get_copy_constructor();
   if (constructor != (CPPInstance *)NULL) {
   if (constructor != (CPPInstance *)NULL) {
     // It has a copy constructor.
     // It has a copy constructor.
@@ -378,25 +575,144 @@ is_copy_constructible(CPPVisibility min_vis) const {
     }
     }
   }
   }
 
 
-  // Check that we don't have pure virtual methods.
+  return true;
+}
+
+/**
+ * Returns true if the type is move-constructible.
+ */
+bool CPPStructType::
+is_move_constructible(CPPVisibility min_vis) const {
+  CPPInstance *constructor = get_move_constructor();
+  if (constructor != (CPPInstance *)NULL) {
+    // It has a user-declared move constructor.
+    if (constructor->_vis > min_vis) {
+      // Inaccessible move constructor.
+      return false;
+    }
+
+    if (constructor->_storage_class & CPPInstance::SC_deleted) {
+      // It is deleted.
+      return false;
+    }
+
+    if (is_abstract()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  return is_copy_constructible(min_vis);
+}
+
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPStructType::
+is_destructible(CPPVisibility min_vis) const {
+  // Do we have an explicit destructor?
+  CPPInstance *destructor = get_destructor();
+  if (destructor != (CPPInstance *)NULL) {
+    if (destructor->_vis > min_vis) {
+      // Yes, but it's inaccessible.
+      return false;
+    }
+
+    if (destructor->_storage_class & CPPInstance::SC_deleted) {
+      // Yes, but it's explicitly been deleted.
+      return false;
+    }
+
+    return true;
+  }
+
+  // Make sure all base classes are destructible.
+  Derivation::const_iterator di;
+  for (di = _derivation.begin(); di != _derivation.end(); ++di) {
+    CPPStructType *base = (*di)._base->as_struct_type();
+    if (base != NULL && !base->is_destructible(V_protected)) {
+      return false;
+    }
+  }
+
+  assert(_scope != NULL);
+
+  // Make sure all members are destructible.
+  CPPScope::Variables::const_iterator vi;
+  for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
+    CPPInstance *instance = (*vi).second;
+    assert(instance != NULL);
+
+    if (instance->_storage_class & CPPInstance::SC_static) {
+      // Static members don't count.
+      continue;
+    }
+
+    // If the data member is not destructible, no go.
+    assert(instance->_type != NULL);
+    if (!instance->_type->is_destructible()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+/**
+ * Returns true if variables of this type may be implicitly converted to
+ * the other type.
+ */
+bool CPPStructType::
+is_convertible_to(const CPPType *other) const {
+  if (CPPType::is_convertible_to(other)) {
+    return true;
+  }
+
+  // Check all typecast operators to see whether we can cast to a type that is
+  // convertible to the other type.
   CPPScope::Functions::const_iterator fi;
   CPPScope::Functions::const_iterator fi;
-  for (fi = _scope->_functions.begin();
-       fi != _scope->_functions.end();
-       ++fi) {
+  for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
     CPPFunctionGroup *fgroup = (*fi).second;
     CPPFunctionGroup *fgroup = (*fi).second;
+
     CPPFunctionGroup::Instances::const_iterator ii;
     CPPFunctionGroup::Instances::const_iterator ii;
-    for (ii = fgroup->_instances.begin();
-         ii != fgroup->_instances.end();
-         ++ii) {
+    for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) {
       CPPInstance *inst = (*ii);
       CPPInstance *inst = (*ii);
-      if (inst->_storage_class & CPPInstance::SC_pure_virtual) {
-        // Here's a pure virtual function.
-        return false;
+
+      if (inst->_storage_class & (CPPInstance::SC_deleted | CPPInstance::SC_static | CPPInstance::SC_explicit)) {
+        // Exclude static/deleted/explicit methods.
+        continue;
+      }
+
+      // Also, the instance needs to be publicly visible.
+      if (inst->_vis > V_public) {
+        continue;
+      }
+
+      assert(inst->_type != (CPPType *)NULL);
+      CPPFunctionType *ftype = inst->_type->as_function_type();
+      assert(ftype != (CPPFunctionType *)NULL);
+
+      if (ftype->_return_type != NULL &&
+          (ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
+        // Yes, this is a typecast operator.  Test using the return type.
+        if (ftype->_return_type->is_convertible_to(other)) {
+          return true;
+        }
       }
       }
     }
     }
   }
   }
 
 
-  return true;
+  // Check whether any of the base classes are convertible.
+  Derivation::const_iterator di;
+  for (di = _derivation.begin(); di != _derivation.end(); ++di) {
+    CPPStructType *base = (*di)._base->as_struct_type();
+    if (base != NULL && (*di)._vis <= V_public && !base->is_convertible_to(other)) {
+      return true;
+    }
+  }
+
+  return false;
 }
 }
 
 
 /**
 /**
@@ -420,6 +736,30 @@ check_virtual() const {
   return !funcs.empty();
   return !funcs.empty();
 }
 }
 
 
+/**
+ * Returns true if this class, or any of its base classes, has a virtual
+ * destructor.
+ */
+bool CPPStructType::
+has_virtual_destructor() const {
+  CPPInstance *destructor = get_destructor();
+  if (destructor != NULL) {
+    if (destructor->_storage_class & CPPInstance::SC_virtual) {
+      return true;
+    }
+  }
+
+  Derivation::const_iterator di;
+  for (di = _derivation.begin(); di != _derivation.end(); ++di) {
+    CPPStructType *base = (*di)._base->as_struct_type();
+    if (base != NULL && base->has_virtual_destructor()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /**
 /**
  * Returns true if this declaration is an actual, factual declaration, or
  * Returns true if this declaration is an actual, factual declaration, or
  * false if some part of the declaration depends on a template parameter which
  * false if some part of the declaration depends on a template parameter which
@@ -459,7 +799,7 @@ get_constructor() const {
 
 
 /**
 /**
  * Returns the default constructor defined for the struct type, or NULL if
  * Returns the default constructor defined for the struct type, or NULL if
- * there is none.
+ * there is no user-declared constructor that takes 0 arguments.
  */
  */
 CPPInstance *CPPStructType::
 CPPInstance *CPPStructType::
 get_default_constructor() const {
 get_default_constructor() const {
@@ -490,7 +830,7 @@ get_default_constructor() const {
 
 
 /**
 /**
  * Returns the copy constructor defined for the struct type, or NULL if no
  * Returns the copy constructor defined for the struct type, or NULL if no
- * copy constructor exists.
+ * user-declared copy constructor exists.
  */
  */
 CPPInstance *CPPStructType::
 CPPInstance *CPPStructType::
 get_copy_constructor() const {
 get_copy_constructor() const {
@@ -519,7 +859,7 @@ get_copy_constructor() const {
 
 
 /**
 /**
  * Returns the move constructor defined for the struct type, or NULL if no
  * Returns the move constructor defined for the struct type, or NULL if no
- * move constructor exists.
+ * user-declared move constructor exists.
  */
  */
 CPPInstance *CPPStructType::
 CPPInstance *CPPStructType::
 get_move_constructor() const {
 get_move_constructor() const {
@@ -548,7 +888,7 @@ get_move_constructor() const {
 
 
 /**
 /**
  * Returns the destructor defined for the struct type, if any, or NULL if no
  * Returns the destructor defined for the struct type, if any, or NULL if no
- * destructor is found.
+ * user-declared destructor is found.
  */
  */
 CPPInstance *CPPStructType::
 CPPInstance *CPPStructType::
 get_destructor() const {
 get_destructor() const {
@@ -854,7 +1194,7 @@ get_virtual_funcs(VFunctions &funcs) const {
           CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
           CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
           assert(new_ftype != (CPPFunctionType *)NULL);
           assert(new_ftype != (CPPFunctionType *)NULL);
 
 
-          if (new_ftype->is_equivalent_function(*base_ftype)) {
+          if (new_ftype->match_virtual_override(*base_ftype)) {
             // It's a match!  We now know it's virtual.  Erase this function
             // It's a match!  We now know it's virtual.  Erase this function
             // from the list, so we can add it back in below.
             // from the list, so we can add it back in below.
             funcs.erase(vfi);
             funcs.erase(vfi);

+ 12 - 0
dtool/src/cppparser/cppStructType.h

@@ -44,14 +44,26 @@ public:
   CPPScope *get_scope() const;
   CPPScope *get_scope() const;
 
 
   bool is_abstract() const;
   bool is_abstract() const;
+  bool is_base_of(const CPPStructType *other) const;
+  bool is_empty() const;
+  bool is_polymorphic() const;
   bool check_virtual() const;
   bool check_virtual() const;
+  bool has_virtual_destructor() const;
   virtual bool is_fully_specified() const;
   virtual bool is_fully_specified() const;
   virtual bool is_incomplete() const;
   virtual bool is_incomplete() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *arg_type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
   bool is_default_constructible(CPPVisibility min_vis) const;
   bool is_default_constructible(CPPVisibility min_vis) const;
   bool is_copy_constructible(CPPVisibility min_vis) const;
   bool is_copy_constructible(CPPVisibility min_vis) const;
+  bool is_move_constructible(CPPVisibility min_vis) const;
+  bool is_destructible(CPPVisibility min_vis) const;
+  virtual bool is_convertible_to(const CPPType *other) const;
+
+  inline bool is_final() const { return _final; }
 
 
   CPPFunctionGroup *get_constructor() const;
   CPPFunctionGroup *get_constructor() const;
   CPPInstance *get_default_constructor() const;
   CPPInstance *get_default_constructor() const;

+ 4 - 2
dtool/src/cppparser/cppTemplateScope.cxx

@@ -97,8 +97,10 @@ add_template_parameter(CPPDeclaration *param) {
   CPPClassTemplateParameter *cl = param->as_class_template_parameter();
   CPPClassTemplateParameter *cl = param->as_class_template_parameter();
   if (cl != NULL) {
   if (cl != NULL) {
     // Create an implicit typedef for this class parameter.
     // Create an implicit typedef for this class parameter.
-    string name = cl->_ident->get_local_name();
-    _types[name] = cl;
+    if (cl->_ident != NULL) {
+      string name = cl->_ident->get_local_name();
+      _types[name] = cl;
+    }
   }
   }
 
 
   CPPInstance *inst = param->as_instance();
   CPPInstance *inst = param->as_instance();

+ 8 - 0
dtool/src/cppparser/cppToken.cxx

@@ -252,6 +252,14 @@ output(ostream &out) const {
     out << "RSHIFTEQUAL";
     out << "RSHIFTEQUAL";
     break;
     break;
 
 
+  case ATTR_LEFT:
+    out << "ATTR_LEFT";
+    break;
+
+  case ATTR_RIGHT:
+    out << "ATTR_RIGHT";
+    break;
+
   case KW_BOOL:
   case KW_BOOL:
     out << "KW_BOOL";
     out << "KW_BOOL";
     break;
     break;

+ 175 - 0
dtool/src/cppparser/cppType.cxx

@@ -12,7 +12,12 @@
  */
  */
 
 
 #include "cppType.h"
 #include "cppType.h"
+#include "cppConstType.h"
+#include "cppPointerType.h"
+#include "cppReferenceType.h"
+#include "cppStructType.h"
 #include "cppTypedefType.h"
 #include "cppTypedefType.h"
+#include "cppExtensionType.h"
 #include <algorithm>
 #include <algorithm>
 
 
 CPPType::Types CPPType::_types;
 CPPType::Types CPPType::_types;
@@ -57,6 +62,22 @@ is_tbd() const {
   return false;
   return false;
 }
 }
 
 
+/**
+ * Returns true if the type is considered a fundamental type.
+ */
+bool CPPType::
+is_fundamental() const {
+  return false;
+}
+
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPType::
+is_standard_layout() const {
+  return false;
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -65,6 +86,14 @@ is_trivial() const {
   return false;
   return false;
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPType::
+is_constructible(const CPPType *given_type) const {
+  return false;
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
@@ -81,6 +110,14 @@ is_copy_constructible() const {
   return false;
   return false;
 }
 }
 
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPType::
+is_destructible() const {
+  return !is_incomplete();
+}
+
 /**
 /**
  * Returns true if the type is a special parameter expression type.
  * Returns true if the type is a special parameter expression type.
  *
  *
@@ -92,6 +129,136 @@ is_parameter_expr() const {
   return false;
   return false;
 }
 }
 
 
+/**
+ * Returns true if this is an enum type, or a typedef to an enum type.
+ */
+bool CPPType::
+is_enum() const {
+  const CPPTypedefType *td_type = as_typedef_type();
+  if (td_type != NULL) {
+    return td_type->_type->is_enum();
+  }
+  const CPPExtensionType *ext_type = as_extension_type();
+  if (ext_type != NULL) {
+    return ext_type->_type == CPPExtensionType::T_enum ||
+           ext_type->_type == CPPExtensionType::T_enum_struct ||
+           ext_type->_type == CPPExtensionType::T_enum_class;
+  }
+  return false;
+}
+
+/**
+ * Returns true if this is a const type, or a typedef to a const type.
+ */
+bool CPPType::
+is_const() const {
+  const CPPTypedefType *td_type = as_typedef_type();
+  if (td_type != NULL) {
+    return td_type->_type->is_const();
+  }
+  return get_subtype() == ST_const;
+}
+
+/**
+ * Returns true if this is a reference type, or a typedef to a reference type.
+ */
+bool CPPType::
+is_reference() const {
+  const CPPTypedefType *td_type = as_typedef_type();
+  if (td_type != NULL) {
+    return td_type->_type->is_reference();
+  }
+  return get_subtype() == ST_reference;
+}
+
+/**
+ * Returns true if this is an unqualified or cv-qualified pointer type, or a
+ * typedef to one.
+ */
+bool CPPType::
+is_pointer() const {
+  const CPPTypedefType *td_type = as_typedef_type();
+  if (td_type != NULL) {
+    return td_type->_type->is_pointer();
+  }
+  const CPPConstType *const_type = as_const_type();
+  if (const_type != NULL) {
+    return const_type->_wrapped_around->is_pointer();
+  }
+  return get_subtype() == ST_pointer;
+}
+
+/**
+ * Returns the type with any const qualifier stripped off.  Will follow
+ * typedefs, but only if necessary.
+ */
+CPPType *CPPType::
+remove_const() {
+  const CPPTypedefType *td_type = as_typedef_type();
+  if (td_type != NULL) {
+    CPPType *unwrapped = td_type->_type->remove_const();
+    if (unwrapped != td_type->_type) {
+      return unwrapped;
+    } else {
+      return this;
+    }
+  }
+  const CPPConstType *const_type = as_const_type();
+  if (const_type != NULL) {
+    return const_type->_wrapped_around->remove_const();
+  }
+  return this;
+}
+
+/**
+ * Returns the type with any reference stripped off.
+ */
+CPPType *CPPType::
+remove_reference() {
+  const CPPTypedefType *td_type = as_typedef_type();
+  if (td_type != NULL) {
+    CPPType *unwrapped = td_type->_type->remove_reference();
+    if (unwrapped != td_type->_type) {
+      return unwrapped;
+    } else {
+      return this;
+    }
+  }
+  const CPPReferenceType *ref_type = as_reference_type();
+  if (ref_type != NULL) {
+    return ref_type->_pointing_at;
+  }
+  return this;
+}
+
+/**
+ * Returns the type with any pointer and cv-qualifiers stripped off.
+ */
+CPPType *CPPType::
+remove_pointer() {
+  switch (get_subtype()) {
+  case ST_typedef:
+    {
+      const CPPTypedefType *td_type = as_typedef_type();
+      CPPType *unwrapped = td_type->_type->remove_pointer();
+      if (unwrapped != td_type->_type) {
+        return unwrapped;
+      } else {
+        return this;
+      }
+    }
+
+  case ST_pointer:
+    return ((const CPPPointerType *)this)->_pointing_at;
+
+  case ST_const:
+    return ((const CPPConstType *)this)->_wrapped_around->remove_pointer();
+
+  default:
+    return this;
+  }
+}
+
 /**
 /**
  * Returns true if the type has even been typedef'ed and therefore has a
  * Returns true if the type has even been typedef'ed and therefore has a
  * simple name available to stand for it.  Extension types are all implicitly
  * simple name available to stand for it.  Extension types are all implicitly
@@ -229,6 +396,14 @@ is_equivalent(const CPPType &other) const {
   return is_equal(&other);
   return is_equal(&other);
 }
 }
 
 
+/**
+ * Returns true if variables of this type may be implicitly converted to
+ * the other type.
+ */
+bool CPPType::
+is_convertible_to(const CPPType *other) const {
+  return other->is_constructible(this);
+}
 
 
 /**
 /**
  * Formats a C++-looking line that defines an instance of the given type, with
  * Formats a C++-looking line that defines an instance of the given type, with

+ 17 - 0
dtool/src/cppparser/cppType.h

@@ -45,11 +45,27 @@ public:
                                 CPPScope *global_scope);
                                 CPPScope *global_scope);
 
 
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_fundamental() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
   virtual bool is_parameter_expr() const;
   virtual bool is_parameter_expr() const;
 
 
+  // Convenience methods.
+  bool is_enum() const;
+  bool is_const() const;
+  bool is_reference() const;
+  bool is_pointer() const;
+
+  CPPType *remove_const();
+  inline CPPType *remove_volatile() { return this; }
+  inline CPPType *remove_cv() { return remove_const(); };
+  CPPType *remove_reference();
+  CPPType *remove_pointer();
+
   bool has_typedef_name() const;
   bool has_typedef_name() const;
   string get_typedef_name(CPPScope *scope = NULL) const;
   string get_typedef_name(CPPScope *scope = NULL) const;
 
 
@@ -61,6 +77,7 @@ public:
   string get_alt_name(int n) const;
   string get_alt_name(int n) const;
 
 
   virtual bool is_incomplete() const;
   virtual bool is_incomplete() const;
+  virtual bool is_convertible_to(const CPPType *other) const;
   virtual bool is_equivalent(const CPPType &other) const;
   virtual bool is_equivalent(const CPPType &other) const;
 
 
   void output_instance(ostream &out, const string &name,
   void output_instance(ostream &out, const string &name,

+ 41 - 0
dtool/src/cppparser/cppTypedefType.cxx

@@ -157,6 +157,22 @@ is_tbd() const {
   return _type->is_tbd();
   return _type->is_tbd();
 }
 }
 
 
+/**
+ * Returns true if the type is considered a fundamental type.
+ */
+bool CPPTypedefType::
+is_fundamental() const {
+  return _type->is_fundamental();
+}
+
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPTypedefType::
+is_standard_layout() const {
+  return _type->is_standard_layout();
+}
+
 /**
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
  */
@@ -165,6 +181,14 @@ is_trivial() const {
   return _type->is_trivial();
   return _type->is_trivial();
 }
 }
 
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPTypedefType::
+is_constructible(const CPPType *given_type) const {
+  return _type->is_constructible(given_type);
+}
+
 /**
 /**
  * Returns true if the type is default-constructible.
  * Returns true if the type is default-constructible.
  */
  */
@@ -181,6 +205,14 @@ is_copy_constructible() const {
   return _type->is_copy_constructible();
   return _type->is_copy_constructible();
 }
 }
 
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPTypedefType::
+is_destructible() const {
+  return _type->is_destructible();
+}
+
 /**
 /**
  * Returns true if this declaration is an actual, factual declaration, or
  * Returns true if this declaration is an actual, factual declaration, or
  * false if some part of the declaration depends on a template parameter which
  * false if some part of the declaration depends on a template parameter which
@@ -300,6 +332,15 @@ resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
   return this;
   return this;
 }
 }
 
 
+/**
+ * Returns true if variables of this type may be implicitly converted to
+ * the other type.
+ */
+bool CPPTypedefType::
+is_convertible_to(const CPPType *other) const {
+  return _type->is_convertible_to(other);
+}
+
 /**
 /**
  * This is a little more forgiving than is_equal(): it returns true if the
  * This is a little more forgiving than is_equal(): it returns true if the
  * types appear to be referring to the same thing, even if they may have
  * types appear to be referring to the same thing, even if they may have

+ 5 - 0
dtool/src/cppparser/cppTypedefType.h

@@ -42,9 +42,13 @@ public:
 
 
   virtual bool is_incomplete() const;
   virtual bool is_incomplete() const;
   virtual bool is_tbd() const;
   virtual bool is_tbd() const;
+  virtual bool is_fundamental() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
 
 
   virtual bool is_fully_specified() const;
   virtual bool is_fully_specified() const;
 
 
@@ -60,6 +64,7 @@ public:
   virtual CPPType *resolve_type(CPPScope *current_scope,
   virtual CPPType *resolve_type(CPPScope *current_scope,
                                 CPPScope *global_scope);
                                 CPPScope *global_scope);
 
 
+  virtual bool is_convertible_to(const CPPType *other) const;
   virtual bool is_equivalent(const CPPType &other) const;
   virtual bool is_equivalent(const CPPType &other) const;
 
 
   virtual void output(ostream &out, int indent_level, CPPScope *scope,
   virtual void output(ostream &out, int indent_level, CPPScope *scope,

+ 1 - 0
dtool/src/cppparser/p3cppParser_composite1.cxx

@@ -2,6 +2,7 @@
 #include "cppFunctionType.cxx"
 #include "cppFunctionType.cxx"
 #include "cppGlobals.cxx"
 #include "cppGlobals.cxx"
 #include "cppCommentBlock.cxx"
 #include "cppCommentBlock.cxx"
+#include "cppClosureType.cxx"
 #include "cppConstType.cxx"
 #include "cppConstType.cxx"
 #include "cppDeclaration.cxx"
 #include "cppDeclaration.cxx"
 #include "cppMakeProperty.cxx"
 #include "cppMakeProperty.cxx"

+ 9 - 2
dtool/src/dtoolbase/deletedBufferChain.cxx

@@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) {
   assert(size <= _buffer_size);
   assert(size <= _buffer_size);
 
 
   // Determine how much space to allocate.
   // Determine how much space to allocate.
-  const size_t alloc_size = _buffer_size + flag_reserved_bytes;
+  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1;
 
 
   ObjectNode *obj;
   ObjectNode *obj;
 
 
@@ -69,7 +69,10 @@ allocate(size_t size, TypeHandle type_handle) {
   // If we get here, the deleted_chain is empty; we have to allocate a new
   // If we get here, the deleted_chain is empty; we have to allocate a new
   // object from the system pool.
   // object from the system pool.
 
 
-  obj = (ObjectNode *)NeverFreeMemory::alloc(alloc_size);
+  // Allocate memory, and make sure the object starts at the proper alignment.
+  void *mem = NeverFreeMemory::alloc(alloc_size);
+  intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment();
+  obj = (ObjectNode *)((uintptr_t)mem + pad);
 
 
 #ifdef USE_DELETEDCHAINFLAG
 #ifdef USE_DELETEDCHAINFLAG
   obj->_flag = DCF_alive;
   obj->_flag = DCF_alive;
@@ -77,6 +80,10 @@ allocate(size_t size, TypeHandle type_handle) {
 
 
   void *ptr = node_to_buffer(obj);
   void *ptr = node_to_buffer(obj);
 
 
+#ifndef NDEBUG
+  assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0);
+#endif
+
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
   type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE

+ 1 - 5
dtool/src/dtoolbase/deletedBufferChain.h

@@ -95,12 +95,8 @@ private:
   // Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
   // Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
   static const size_t flag_reserved_bytes = 0;
   static const size_t flag_reserved_bytes = 0;
 
 
-#elif defined(LINMATH_ALIGN)
-  // With SSE2 alignment, we need all 16 bytes to preserve alignment.
-  static const size_t flag_reserved_bytes = 16;
-
 #else
 #else
-  // Otherwise, we only need enough space for the Integer itself.
+  // Otherwise, we need space for the integer.
   static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
   static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
 #endif  // USE_DELETEDCHAINFLAG
 #endif  // USE_DELETEDCHAINFLAG
 
 

+ 7 - 2
dtool/src/dtoolbase/dlmalloc_src.cxx

@@ -587,8 +587,11 @@ MAX_RELEASE_CHECK_RATE   default: 4095 unless not HAVE_MMAP
 #define MAX_SIZE_T           (~(size_t)0)
 #define MAX_SIZE_T           (~(size_t)0)
 
 
 #ifndef USE_LOCKS /* ensure true if spin or recursive locks set */
 #ifndef USE_LOCKS /* ensure true if spin or recursive locks set */
-#define USE_LOCKS  ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \
-                    (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0))
+#if (defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)
+#define USE_LOCKS 1
+#else
+#define USE_LOCKS 0
+#endif
 #endif /* USE_LOCKS */
 #endif /* USE_LOCKS */
 
 
 #if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */
 #if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */
@@ -647,7 +650,9 @@ MAX_RELEASE_CHECK_RATE   default: 4095 unless not HAVE_MMAP
 #ifndef HAVE_MREMAP
 #ifndef HAVE_MREMAP
 #ifdef linux
 #ifdef linux
 #define HAVE_MREMAP 1
 #define HAVE_MREMAP 1
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE /* Turns on mremap() definition */
 #define _GNU_SOURCE /* Turns on mremap() definition */
+#endif
 #else   /* linux */
 #else   /* linux */
 #define HAVE_MREMAP 0
 #define HAVE_MREMAP 0
 #endif  /* linux */
 #endif  /* linux */

+ 6 - 1
dtool/src/dtoolbase/dtoolbase.h

@@ -339,21 +339,26 @@ typedef struct _object PyObject;
 #define ALIGN_4BYTE
 #define ALIGN_4BYTE
 #define ALIGN_8BYTE
 #define ALIGN_8BYTE
 #define ALIGN_16BYTE
 #define ALIGN_16BYTE
+#define ALIGN_32BYTE
 #define ALIGN_64BYTE
 #define ALIGN_64BYTE
 #elif defined(_MSC_VER)
 #elif defined(_MSC_VER)
 #define ALIGN_4BYTE __declspec(align(4))
 #define ALIGN_4BYTE __declspec(align(4))
 #define ALIGN_8BYTE __declspec(align(8))
 #define ALIGN_8BYTE __declspec(align(8))
 #define ALIGN_16BYTE __declspec(align(16))
 #define ALIGN_16BYTE __declspec(align(16))
+#define ALIGN_32BYTE __declspec(align(32))
 #define ALIGN_64BYTE __declspec(align(64))
 #define ALIGN_64BYTE __declspec(align(64))
 #elif defined(__GNUC__)
 #elif defined(__GNUC__)
 #define ALIGN_4BYTE __attribute__ ((aligned (4)))
 #define ALIGN_4BYTE __attribute__ ((aligned (4)))
 #define ALIGN_8BYTE __attribute__ ((aligned (8)))
 #define ALIGN_8BYTE __attribute__ ((aligned (8)))
 #define ALIGN_16BYTE __attribute__ ((aligned (16)))
 #define ALIGN_16BYTE __attribute__ ((aligned (16)))
+#define ALIGN_32BYTE __attribute__ ((aligned (32)))
 #define ALIGN_64BYTE __attribute__ ((aligned (64)))
 #define ALIGN_64BYTE __attribute__ ((aligned (64)))
 #else
 #else
 #define ALIGN_4BYTE
 #define ALIGN_4BYTE
 #define ALIGN_8BYTE
 #define ALIGN_8BYTE
 #define ALIGN_16BYTE
 #define ALIGN_16BYTE
+#define ALIGN_32BYTE
+#define ALIGN_64BYTE
 #endif
 #endif
 
 
 // Do we need to implement memory-alignment enforcement within the MemoryHook
 // Do we need to implement memory-alignment enforcement within the MemoryHook
@@ -374,7 +379,7 @@ typedef struct _object PyObject;
 // externally.
 // externally.
 #define MEMORY_HOOK_DO_ALIGN 1
 #define MEMORY_HOOK_DO_ALIGN 1
 
 
-#elif defined(IS_OSX) || defined(_WIN64)
+#elif (defined(IS_OSX) || defined(_WIN64)) && !defined(__AVX__)
 // The OS-provided malloc implementation will do the required alignment.
 // The OS-provided malloc implementation will do the required alignment.
 #undef MEMORY_HOOK_DO_ALIGN
 #undef MEMORY_HOOK_DO_ALIGN
 
 

+ 50 - 3
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -39,6 +39,10 @@ using namespace std;
 #define OVERRIDE override
 #define OVERRIDE override
 #define MOVE(x) x
 #define MOVE(x) x
 #define DEFAULT_CTOR = default
 #define DEFAULT_CTOR = default
+#define DEFAULT_DTOR = default
+#define DEFAULT_ASSIGN = default
+#define DELETED = delete
+#define DELETED_ASSIGN = delete
 
 
 #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
 #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
 
 
@@ -75,6 +79,7 @@ typedef int ios_seekdir;
 #endif
 #endif
 
 
 #include <string>
 #include <string>
+#include <utility>
 
 
 #ifdef HAVE_NAMESPACE
 #ifdef HAVE_NAMESPACE
 using namespace std;
 using namespace std;
@@ -114,6 +119,20 @@ typedef ios::iostate ios_iostate;
 typedef ios::seekdir ios_seekdir;
 typedef ios::seekdir ios_seekdir;
 #endif
 #endif
 
 
+// Apple has an outdated libstdc++.  Not all is lost, though, as we can fill
+// in some important missing functions.
+#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719
+typedef decltype(nullptr) nullptr_t;
+
+template<class T> struct remove_reference      {typedef T type;};
+template<class T> struct remove_reference<T&>  {typedef T type;};
+template<class T> struct remove_reference<T&& >{typedef T type;};
+
+template<class T> typename remove_reference<T>::type &&move(T &&t) {
+  return static_cast<typename remove_reference<T>::type&&>(t);
+}
+#endif
+
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #define ALWAYS_INLINE __forceinline
 #define ALWAYS_INLINE __forceinline
 #elif defined(__GNUC__)
 #elif defined(__GNUC__)
@@ -134,7 +153,9 @@ typedef ios::seekdir ios_seekdir;
 // Determine the availability of C++11 features.
 // Determine the availability of C++11 features.
 #if defined(__has_extension) // Clang magic.
 #if defined(__has_extension) // Clang magic.
 #  if __has_extension(cxx_constexpr)
 #  if __has_extension(cxx_constexpr)
-#    define CONSTEXPR constexpr
+#    if !defined(__apple_build_version__) || __apple_build_version__ >= 5000000
+#      define CONSTEXPR constexpr
+#    endif
 #  endif
 #  endif
 #  if __has_extension(cxx_noexcept)
 #  if __has_extension(cxx_noexcept)
 #    define NOEXCEPT noexcept
 #    define NOEXCEPT noexcept
@@ -149,11 +170,16 @@ typedef ios::seekdir ios_seekdir;
 #  endif
 #  endif
 #  if __has_extension(cxx_defaulted_functions)
 #  if __has_extension(cxx_defaulted_functions)
 #     define DEFAULT_CTOR = default
 #     define DEFAULT_CTOR = default
+#     define DEFAULT_DTOR = default
+#     define DEFAULT_ASSIGN = default
+#  endif
+#  if __has_extension(cxx_deleted_functions)
+#     define DELETED = delete
 #  endif
 #  endif
 #elif defined(__GNUC__) && (__cplusplus >= 201103L) // GCC
 #elif defined(__GNUC__) && (__cplusplus >= 201103L) // GCC
 
 
 // GCC defines several macros which we can query.  List of all supported
 // GCC defines several macros which we can query.  List of all supported
-// builtin macros: https:gcc.gnu.orgprojectscxx0x.html
+// builtin macros: https://gcc.gnu.org/projects/cxx-status.html
 #  if __cpp_constexpr >= 200704
 #  if __cpp_constexpr >= 200704
 #    define CONSTEXPR constexpr
 #    define CONSTEXPR constexpr
 #  endif
 #  endif
@@ -161,6 +187,9 @@ typedef ios::seekdir ios_seekdir;
 // Starting at GCC 4.4
 // Starting at GCC 4.4
 #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
 #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
 #  define DEFAULT_CTOR = default
 #  define DEFAULT_CTOR = default
+#  define DEFAULT_DTOR = default
+#  define DEFAULT_ASSIGN = default
+#  define DELETED = delete
 #  endif
 #  endif
 
 
 // Starting at GCC 4.6
 // Starting at GCC 4.6
@@ -183,7 +212,6 @@ typedef ios::seekdir ios_seekdir;
 #  define FINAL final
 #  define FINAL final
 #  define OVERRIDE override
 #  define OVERRIDE override
 #  define MOVE(x) move(x)
 #  define MOVE(x) move(x)
-#  define DEFAULT_CTOR = default
 #elif defined(_MSC_VER) && _MSC_VER >= 1600 // Visual Studio 2010
 #elif defined(_MSC_VER) && _MSC_VER >= 1600 // Visual Studio 2010
 #  define NOEXCEPT throw()
 #  define NOEXCEPT throw()
 #  define OVERRIDE override
 #  define OVERRIDE override
@@ -192,6 +220,13 @@ typedef ios::seekdir ios_seekdir;
 #  define MOVE(x) move(x)
 #  define MOVE(x) move(x)
 #endif
 #endif
 
 
+#if defined(_MSC_VER) && _MSC_VER >= 1800 // Visual Studio 2013
+#  define DEFAULT_CTOR = default
+#  define DEFAULT_DTOR = default
+#  define DEFAULT_ASSIGN = default
+#  define DELETED = delete
+#endif
+
 // Fallbacks if features are not supported
 // Fallbacks if features are not supported
 #ifndef CONSTEXPR
 #ifndef CONSTEXPR
 #  define CONSTEXPR INLINE
 #  define CONSTEXPR INLINE
@@ -211,6 +246,18 @@ typedef ios::seekdir ios_seekdir;
 #ifndef DEFAULT_CTOR
 #ifndef DEFAULT_CTOR
 #  define DEFAULT_CTOR {}
 #  define DEFAULT_CTOR {}
 #endif
 #endif
+#ifndef DEFAULT_DTOR
+#  define DEFAULT_DTOR {}
+#endif
+#ifndef DEFAULT_ASSIGN
+#  define DEFAULT_ASSIGN {return *this;}
+#endif
+#ifndef DELETED
+#  define DELETED {assert(false);}
+#  define DELETED_ASSIGN {assert(false);return *this;}
+#else
+#  define DELETED_ASSIGN DELETED
+#endif
 
 
 
 
 #if !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)
 #if !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)

+ 16 - 4
dtool/src/dtoolbase/memoryHook.I

@@ -43,10 +43,16 @@ get_memory_alignment() {
 #ifdef LINMATH_ALIGN
 #ifdef LINMATH_ALIGN
   // We require 16-byte alignment of certain structures, to support SSE2.  We
   // We require 16-byte alignment of certain structures, to support SSE2.  We
   // don't strictly have to align *everything*, but it's just easier to do so.
   // don't strictly have to align *everything*, but it's just easier to do so.
+#ifdef __AVX__
+  // Eigen requires 32-byte alignment when using AVX instructions.
+  const size_t alignment_size = 32;
+#else
   const size_t alignment_size = 16;
   const size_t alignment_size = 16;
+#endif
 #else
 #else
-  // Otherwise, use word alignment.
-  const size_t alignment_size = sizeof(void *);
+  // Otherwise, align to two words.  This seems to be pretty standard to the
+  // point where some code may rely on this being the case.
+  const size_t alignment_size = sizeof(void *) * 2;
 #endif
 #endif
   return alignment_size;
   return alignment_size;
 }
 }
@@ -64,7 +70,12 @@ get_header_reserved_bytes() {
 #ifdef LINMATH_ALIGN
 #ifdef LINMATH_ALIGN
   // If we're doing SSE2 alignment, we must reserve a full 16-byte block,
   // If we're doing SSE2 alignment, we must reserve a full 16-byte block,
   // since anything less than that will spoil the alignment.
   // since anything less than that will spoil the alignment.
+#ifdef __AVX__
+  // Eigen requires 32-byte alignment when using AVX instructions.
+  static const size_t header_reserved_bytes = 32;
+#else
   static const size_t header_reserved_bytes = 16;
   static const size_t header_reserved_bytes = 16;
+#endif
 
 
 #elif defined(MEMORY_HOOK_DO_ALIGN)
 #elif defined(MEMORY_HOOK_DO_ALIGN)
   // If we're just aligning to words, we reserve a block as big as two words,
   // If we're just aligning to words, we reserve a block as big as two words,
@@ -72,8 +83,9 @@ get_header_reserved_bytes() {
   static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t);
   static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t);
 
 
 #else
 #else
-  // If we're not aligning, we just need space for the word itself.
-  static const size_t header_reserved_bytes = sizeof(size_t);
+  // Virtually all allocators align to two words, so we make sure we preserve
+  // that alignment for the benefit of anyone who relies upon that.
+  static const size_t header_reserved_bytes = sizeof(void *) * 2;
 #endif
 #endif
 
 
   return header_reserved_bytes;
   return header_reserved_bytes;

+ 5 - 0
dtool/src/dtoolbase/memoryHook.cxx

@@ -53,8 +53,13 @@
 // drose: We require 16-byte alignment of certain structures, to
 // drose: We require 16-byte alignment of certain structures, to
 // support SSE2.  We don't strictly have to align *everything*, but
 // support SSE2.  We don't strictly have to align *everything*, but
 // it's just easier to do so.
 // it's just easier to do so.
+#ifdef __AVX__
+// Eigen requires 32-byte alignment when using AVX instructions.
+#define MALLOC_ALIGNMENT ((size_t)32U)
+#else
 #define MALLOC_ALIGNMENT ((size_t)16U)
 #define MALLOC_ALIGNMENT ((size_t)16U)
 #endif
 #endif
+#endif
 
 
 #include "dlmalloc_src.cxx"
 #include "dlmalloc_src.cxx"
 
 

+ 3 - 17
dtool/src/dtoolbase/mutexDummyImpl.I

@@ -14,28 +14,14 @@
 /**
 /**
  *
  *
  */
  */
-INLINE MutexDummyImpl::
-MutexDummyImpl() {
-}
-
-/**
- *
- */
-INLINE MutexDummyImpl::
-~MutexDummyImpl() {
-}
-
-/**
- *
- */
-INLINE void MutexDummyImpl::
+ALWAYS_INLINE void MutexDummyImpl::
 acquire() {
 acquire() {
 }
 }
 
 
 /**
 /**
  *
  *
  */
  */
-INLINE bool MutexDummyImpl::
+ALWAYS_INLINE bool MutexDummyImpl::
 try_acquire() {
 try_acquire() {
   return true;
   return true;
 }
 }
@@ -43,6 +29,6 @@ try_acquire() {
 /**
 /**
  *
  *
  */
  */
-INLINE void MutexDummyImpl::
+ALWAYS_INLINE void MutexDummyImpl::
 release() {
 release() {
 }
 }

+ 9 - 5
dtool/src/dtoolbase/mutexDummyImpl.h

@@ -23,12 +23,16 @@
  */
  */
 class EXPCL_DTOOL MutexDummyImpl {
 class EXPCL_DTOOL MutexDummyImpl {
 public:
 public:
-  INLINE MutexDummyImpl();
-  INLINE ~MutexDummyImpl();
+  CONSTEXPR MutexDummyImpl() DEFAULT_CTOR;
 
 
-  INLINE void acquire();
-  INLINE bool try_acquire();
-  INLINE void release();
+private:
+  MutexDummyImpl(const MutexDummyImpl &copy) DELETED;
+  MutexDummyImpl &operator = (const MutexDummyImpl &copy) DELETED_ASSIGN;
+
+public:
+  ALWAYS_INLINE void acquire();
+  ALWAYS_INLINE bool try_acquire();
+  ALWAYS_INLINE void release();
 };
 };
 
 
 #include "mutexDummyImpl.I"
 #include "mutexDummyImpl.I"

+ 8 - 10
dtool/src/dtoolbase/mutexPosixImpl.I

@@ -14,16 +14,8 @@
 /**
 /**
  *
  *
  */
  */
-INLINE MutexPosixImpl::
-MutexPosixImpl() {
-  TAU_PROFILE("MutexPosixImpl::MutexPosixImpl", " ", TAU_USER);
-  pthread_mutexattr_t attr;
-  pthread_mutexattr_init(&attr);
-  // The symbol PTHREAD_MUTEX_DEFAULT isn't always available?
-  // pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
-  int result = pthread_mutex_init(&_lock, &attr);
-  pthread_mutexattr_destroy(&attr);
-  assert(result == 0);
+CONSTEXPR MutexPosixImpl::
+MutexPosixImpl() NOEXCEPT : _lock(PTHREAD_MUTEX_INITIALIZER) {
 }
 }
 
 
 /**
 /**
@@ -78,6 +70,11 @@ get_posix_lock() {
 /**
 /**
  *
  *
  */
  */
+#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+CONSTEXPR ReMutexPosixImpl::
+ReMutexPosixImpl() NOEXCEPT : _lock(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) {
+}
+#else
 INLINE ReMutexPosixImpl::
 INLINE ReMutexPosixImpl::
 ReMutexPosixImpl() {
 ReMutexPosixImpl() {
   TAU_PROFILE("ReMutexPosixImpl::ReMutexPosixImpl", " ", TAU_USER);
   TAU_PROFILE("ReMutexPosixImpl::ReMutexPosixImpl", " ", TAU_USER);
@@ -88,6 +85,7 @@ ReMutexPosixImpl() {
   pthread_mutexattr_destroy(&attr);
   pthread_mutexattr_destroy(&attr);
   assert(result == 0);
   assert(result == 0);
 }
 }
+#endif
 
 
 /**
 /**
  *
  *

+ 15 - 1
dtool/src/dtoolbase/mutexPosixImpl.h

@@ -28,9 +28,14 @@
  */
  */
 class EXPCL_DTOOL MutexPosixImpl {
 class EXPCL_DTOOL MutexPosixImpl {
 public:
 public:
-  INLINE MutexPosixImpl();
+  CONSTEXPR MutexPosixImpl() NOEXCEPT;
   INLINE ~MutexPosixImpl();
   INLINE ~MutexPosixImpl();
 
 
+private:
+  MutexPosixImpl(const MutexPosixImpl &copy) DELETED;
+  MutexPosixImpl &operator = (const MutexPosixImpl &copy) DELETED_ASSIGN;
+
+public:
   INLINE void acquire();
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE bool try_acquire();
   INLINE void release();
   INLINE void release();
@@ -47,9 +52,18 @@ private:
  */
  */
 class EXPCL_DTOOL ReMutexPosixImpl {
 class EXPCL_DTOOL ReMutexPosixImpl {
 public:
 public:
+#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+  CONSTEXPR ReMutexPosixImpl() NOEXCEPT;
+#else
   INLINE ReMutexPosixImpl();
   INLINE ReMutexPosixImpl();
+#endif
   INLINE ~ReMutexPosixImpl();
   INLINE ~ReMutexPosixImpl();
 
 
+private:
+  ReMutexPosixImpl(const ReMutexPosixImpl &copy) DELETED;
+  ReMutexPosixImpl &operator = (const ReMutexPosixImpl &copy) DELETED;
+
+public:
   INLINE void acquire();
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE bool try_acquire();
   INLINE void release();
   INLINE void release();

+ 2 - 10
dtool/src/dtoolbase/mutexSpinlockImpl.I

@@ -14,16 +14,8 @@
 /**
 /**
  *
  *
  */
  */
-INLINE MutexSpinlockImpl::
-MutexSpinlockImpl() {
-  _lock = 0;
-}
-
-/**
- *
- */
-INLINE MutexSpinlockImpl::
-~MutexSpinlockImpl() {
+CONSTEXPR MutexSpinlockImpl::
+MutexSpinlockImpl() : _lock(0) {
 }
 }
 
 
 /**
 /**

+ 6 - 2
dtool/src/dtoolbase/mutexSpinlockImpl.h

@@ -29,9 +29,13 @@
  */
  */
 class EXPCL_DTOOL MutexSpinlockImpl {
 class EXPCL_DTOOL MutexSpinlockImpl {
 public:
 public:
-  INLINE MutexSpinlockImpl();
-  INLINE ~MutexSpinlockImpl();
+  CONSTEXPR MutexSpinlockImpl();
 
 
+private:
+  MutexSpinlockImpl(const MutexSpinlockImpl &copy) DELETED;
+  MutexSpinlockImpl &operator = (const MutexSpinlockImpl &copy) DELETED_ASSIGN;
+
+public:
   INLINE void acquire();
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE bool try_acquire();
   INLINE void release();
   INLINE void release();

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů