Browse Source

Try to stay compatible with Bison 2.5 (for Ubuntu precise), support C++11 and C++17 static_assert, improve error reporting, handle several gcc keyword aliases, fix bug handling preprocessor expression in which the same manifest occurs more than once

rdb 10 years ago
parent
commit
ba45120eac

File diff suppressed because it is too large
+ 441 - 438
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 40 - 38
dtool/src/cppparser/cppBison.h.prebuilt

@@ -131,25 +131,26 @@ extern int cppyydebug;
      KW_SIGNED = 340,
      KW_SIZEOF = 341,
      KW_STATIC = 342,
-     KW_STATIC_CAST = 343,
-     KW_STRUCT = 344,
-     KW_TEMPLATE = 345,
-     KW_THROW = 346,
-     KW_TRUE = 347,
-     KW_TRY = 348,
-     KW_TYPEDEF = 349,
-     KW_TYPENAME = 350,
-     KW_UNION = 351,
-     KW_UNSIGNED = 352,
-     KW_USING = 353,
-     KW_VIRTUAL = 354,
-     KW_VOID = 355,
-     KW_VOLATILE = 356,
-     KW_WCHAR_T = 357,
-     KW_WHILE = 358,
-     START_CPP = 359,
-     START_CONST_EXPR = 360,
-     START_TYPE = 361
+     KW_STATIC_ASSERT = 343,
+     KW_STATIC_CAST = 344,
+     KW_STRUCT = 345,
+     KW_TEMPLATE = 346,
+     KW_THROW = 347,
+     KW_TRUE = 348,
+     KW_TRY = 349,
+     KW_TYPEDEF = 350,
+     KW_TYPENAME = 351,
+     KW_UNION = 352,
+     KW_UNSIGNED = 353,
+     KW_USING = 354,
+     KW_VIRTUAL = 355,
+     KW_VOID = 356,
+     KW_VOLATILE = 357,
+     KW_WCHAR_T = 358,
+     KW_WHILE = 359,
+     START_CPP = 360,
+     START_CONST_EXPR = 361,
+     START_TYPE = 362
    };
 #endif
 /* Tokens.  */
@@ -238,25 +239,26 @@ extern int cppyydebug;
 #define KW_SIGNED 340
 #define KW_SIZEOF 341
 #define KW_STATIC 342
-#define KW_STATIC_CAST 343
-#define KW_STRUCT 344
-#define KW_TEMPLATE 345
-#define KW_THROW 346
-#define KW_TRUE 347
-#define KW_TRY 348
-#define KW_TYPEDEF 349
-#define KW_TYPENAME 350
-#define KW_UNION 351
-#define KW_UNSIGNED 352
-#define KW_USING 353
-#define KW_VIRTUAL 354
-#define KW_VOID 355
-#define KW_VOLATILE 356
-#define KW_WCHAR_T 357
-#define KW_WHILE 358
-#define START_CPP 359
-#define START_CONST_EXPR 360
-#define START_TYPE 361
+#define KW_STATIC_ASSERT 343
+#define KW_STATIC_CAST 344
+#define KW_STRUCT 345
+#define KW_TEMPLATE 346
+#define KW_THROW 347
+#define KW_TRUE 348
+#define KW_TRY 349
+#define KW_TYPEDEF 350
+#define KW_TYPENAME 351
+#define KW_UNION 352
+#define KW_UNSIGNED 353
+#define KW_USING 354
+#define KW_VIRTUAL 355
+#define KW_VOID 356
+#define KW_VOLATILE 357
+#define KW_WCHAR_T 358
+#define KW_WHILE 359
+#define START_CPP 360
+#define START_CONST_EXPR 361
+#define START_TYPE 362
 
 
 

+ 51 - 5
dtool/src/cppparser/cppBison.yxx

@@ -57,7 +57,7 @@ int yyparse();
 
 static void
 yyerror(const string &msg) {
-  current_lexer->error(msg);
+  current_lexer->error(msg, current_lexer->_last_token_loc);
 }
 
 static void
@@ -199,9 +199,11 @@ pop_struct() {
 
 /* This is a bison-specific declaration to enable recursive calls to
    yyparse().  It changes the calling sequence to yylex(), passing
-   pointers to the current yylval and yylloc.  It also adds a pointer
-   to the current lloc to yyerror, which gives us better diagnostics. */
-%define api.pure full
+   pointers to the current yylval and yylloc.  Bison 2.7 introduces a
+   different syntax that will also pass the current yylloc to yyerror,
+   but we have to support Bison versions as old as 2.5 for now. */
+/*%define api.pure full*/
+%pure-parser
 %locations
 
 %token <u.real> REAL
@@ -288,6 +290,7 @@ pop_struct() {
 %token KW_SIGNED
 %token KW_SIZEOF
 %token KW_STATIC
+%token KW_STATIC_ASSERT
 %token KW_STATIC_CAST
 %token KW_STRUCT
 %token KW_TEMPLATE
@@ -518,10 +521,29 @@ declaration:
     current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
   }
 }
-         | KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
+        | KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
 {
   CPPMakeSeq *make_seq = new CPPMakeSeq($3->get_simple_name(), $5->get_simple_name(), $7->get_simple_name(), @1.file);
   current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
+}
+        | KW_STATIC_ASSERT '(' const_expr ',' string ')'
+{
+  CPPExpression::Result result = $3->evaluate();
+  if (result._type == CPPExpression::RT_error) {
+    yywarning("static_assert requires a constant expression", @3);
+  } else if (!result.as_boolean()) {
+    yywarning("static_assert failed: " + $5, @3);
+  }
+}
+        | KW_STATIC_ASSERT '(' const_expr ')'
+{
+  // This alternative version of static_assert was introduced in C++17.
+  CPPExpression::Result result = $3->evaluate();
+  if (result._type == CPPExpression::RT_error) {
+    yywarning("static_assert requires a constant expression", @3);
+  } else if (!result.as_boolean()) {
+    yywarning("static_assert failed", @3);
+  }
 }
         ;
 
@@ -856,6 +878,9 @@ function_prototype:
 {
   pop_scope();
   CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if (type == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert(type != NULL);
 
   CPPInstanceIdentifier *ii = $4;
@@ -871,6 +896,9 @@ function_prototype:
 {
   pop_scope();
   CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if (type == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert(type != NULL);
 
   CPPInstanceIdentifier *ii = $5;
@@ -1213,6 +1241,9 @@ template_formal_parameter_type:
         | TYPENAME_IDENTIFIER
 {
   $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if ($$ == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert($$ != NULL);
 }
         ;
@@ -1608,6 +1639,9 @@ type:
         | TYPENAME_IDENTIFIER
 {
   $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if ($$ == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert($$ != NULL);
 }
         | KW_TYPENAME name
@@ -1668,6 +1702,9 @@ type_decl:
         | TYPENAME_IDENTIFIER
 {
   $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if ($$ == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert($$ != NULL);
 }
         | KW_TYPENAME name
@@ -1746,6 +1783,9 @@ predefined_type:
         | TYPENAME_IDENTIFIER
 {
   $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if ($$ == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert($$ != NULL);
 }
         | KW_TYPENAME name
@@ -2419,6 +2459,9 @@ const_expr:
 {
   // A constructor call.
   CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if (type == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert(type != NULL);
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
@@ -2888,6 +2931,9 @@ typedefname:
         TYPENAME_IDENTIFIER
 {
   CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if (type == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
   assert(type != NULL);
   $$ = type;
 }

+ 2 - 2
dtool/src/cppparser/cppManifest.cxx

@@ -46,9 +46,9 @@ ExpansionNode(const string &str, bool paste) :
 //  Description:
 ////////////////////////////////////////////////////////////////////
 CPPManifest::
-CPPManifest(const string &args, const CPPFile &file) :
+CPPManifest(const string &args, const cppyyltype &loc) :
   _variadic_param(-1),
-  _file(file),
+  _loc(loc),
   _expr((CPPExpression *)NULL)
 {
   assert(!args.empty());

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

@@ -19,6 +19,7 @@
 
 #include "cppFile.h"
 #include "cppVisibility.h"
+#include "cppBisonDefs.h"
 
 #include "vector_string.h"
 
@@ -31,7 +32,7 @@ class CPPType;
 ////////////////////////////////////////////////////////////////////
 class CPPManifest {
 public:
-  CPPManifest(const string &args, const CPPFile &file = CPPFile());
+  CPPManifest(const string &args, const cppyyltype &loc = {0});
   ~CPPManifest();
 
   static string stringify(const string &source);
@@ -45,7 +46,7 @@ public:
   bool _has_parameters;
   int _num_parameters;
   int _variadic_param;
-  CPPFile _file;
+  cppyyltype _loc;
   CPPExpression *_expr;
 
   // Manifests don't have a visibility in the normal sense.  Normally

+ 25 - 21
dtool/src/cppparser/cppPreprocessor.cxx

@@ -407,6 +407,7 @@ get_next_token0() {
           return token;
         }
         _saved_tokens.push_back(token);
+        _last_token_loc = loc;
         return CPPToken(SCOPING, loc, name, result);
       }
 
@@ -444,10 +445,12 @@ get_next_token0() {
       token_type = TYPENAME_IDENTIFIER;
     }
 
+    _last_token_loc = loc;
     return CPPToken(token_type, loc, name, result);
   }
 
   // This is the normal case: just pass through whatever token we got.
+  _last_token_loc = loc;
   return token;
 }
 
@@ -843,10 +846,6 @@ expand_manifests(const string &input_expr, bool expand_undefined) {
   // Repeatedly scan the expr for any manifest names or defined()
   // function.
 
-  // We'll need to save the set of manifests we've already expanded,
-  // to guard against recursive references.
-  set<const CPPManifest *> already_expanded;
-
   bool manifest_found;
   do {
     manifest_found = false;
@@ -867,10 +866,9 @@ expand_manifests(const string &input_expr, bool expand_undefined) {
           Manifests::const_iterator mi = _manifests.find(ident);
           if (mi != _manifests.end()) {
             const CPPManifest *manifest = (*mi).second;
-            if (already_expanded.insert(manifest).second) {
-              expand_manifest_inline(expr, q, p, (*mi).second);
-              manifest_found = true;
-            }
+            expand_manifest_inline(expr, q, p, (*mi).second);
+            manifest_found = true;
+
           } else if (expand_undefined && ident != "true" && ident != "false") {
             // It is not found.  Expand it to 0.
             expr = expr.substr(0, q) + "0" + expr.substr(p);
@@ -1470,7 +1468,7 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
   if (args.empty()) {
     warning("Ignoring empty #define directive", loc);
   } else {
-    CPPManifest *manifest = new CPPManifest(args, loc.file);
+    CPPManifest *manifest = new CPPManifest(args, loc);
     manifest->_vis = preprocessor_vis;
     if (!manifest->_has_parameters) {
       string expr_string = manifest->expand();
@@ -1479,18 +1477,17 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
       }
     }
 
-    // ok one memory leak here..
-    Manifests::iterator mi = _manifests.find(manifest->_name);
-    if(mi != _manifests.end())
-    {
-        // i do not see a goodway to compare the old and new hmmmm
-        //cerr << "Warning Overwriting Constant " << manifest->_name << "\n";
-        delete mi->second;
-    }
-
-    _manifests[manifest->_name] = manifest;
-
+    pair<Manifests::iterator, bool> result =
+      _manifests.insert(Manifests::value_type(manifest->_name, manifest));
 
+    if (!result.second) {
+      // There was already a macro with this name.  Delete the old.
+      CPPManifest *other = result.first->second;
+      warning("redefinition of macro '" + manifest->_name + "'", loc);
+      warning("previous definition is here", other->_loc);
+      delete other;
+      result.first->second = manifest;
+    }
   }
 }
 
@@ -1560,7 +1557,9 @@ handle_if_directive(const string &args, const YYLTYPE &loc) {
   if (expr != (CPPExpression *)NULL) {
     CPPExpression::Result result = expr->evaluate();
     if (result._type == CPPExpression::RT_error) {
-      warning("Ignoring invalid expression " + args, loc);
+      ostringstream strm;
+      strm << *expr;
+      warning("Ignoring invalid expression " + strm.str(), loc);
     } else {
       expression_result = result.as_integer();
     }
@@ -2302,6 +2301,8 @@ check_keyword(const string &name) {
   if (name == "char32_t") return KW_CHAR32_T;
   if (name == "class") return KW_CLASS;
   if (name == "const") return KW_CONST;
+  if (name == "__const") return KW_CONST;
+  if (name == "__const__") return KW_CONST;
   if (name == "delete") return KW_DELETE;
   if (name == "double") return KW_DOUBLE;
   if (name == "dynamic_cast") return KW_DYNAMIC_CAST;
@@ -2319,6 +2320,8 @@ check_keyword(const string &name) {
   if (name == "goto") return KW_GOTO;
   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 == "int") return KW_INT;
   if (name == "long") return KW_LONG;
   if (name == "__make_property") return KW_MAKE_PROPERTY;
@@ -2337,6 +2340,7 @@ check_keyword(const string &name) {
   if (name == "signed") return KW_SIGNED;
   if (name == "sizeof") return KW_SIZEOF;
   if (name == "static") return KW_STATIC;
+  if (name == "static_assert") return KW_STATIC_ASSERT;
   if (name == "static_cast") return KW_STATIC_CAST;
   if (name == "struct") return KW_STRUCT;
   if (name == "template") return KW_TEMPLATE;

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

@@ -101,6 +101,9 @@ public:
   // incremented), or set it higher to get more debugging information.
   int _verbose;
 
+  // The location of the last token.
+  cppyyltype _last_token_loc;
+
 protected:
   bool init_cpp(const CPPFile &file);
   bool init_const_expr(const string &expr);

+ 3 - 3
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1344,14 +1344,14 @@ scan_manifest(CPPManifest *manifest) {
     return;
   }
 
-  if (manifest->_file.is_c_file()) {
+  if (manifest->_loc.file.is_c_file()) {
     // This #define appears in a .C file.  We can only export
     // manifests defined in a .h file.
     return;
   }
 
-  if (manifest->_file._source != CPPFile::S_local ||
-      in_ignorefile(manifest->_file._filename_as_referenced)) {
+  if (manifest->_loc.file._source != CPPFile::S_local ||
+      in_ignorefile(manifest->_loc.file._filename_as_referenced)) {
     // The manifest is defined in some other package or in an
     // ignorable file.
     return;

+ 2 - 2
makepanda/makepanda.py

@@ -1354,13 +1354,13 @@ def CompileIgate(woutd,wsrc,opts):
     cmd += ' -srcdir %s -I%s' % (srcdir, srcdir)
     cmd += ' -DCPPPARSER -D__STDC__=1 -D__cplusplus=201103L'
     if (COMPILER=="MSVC"):
-        cmd += ' -D__inline -D_X86_ -DWIN32_VC -DWIN32 -D_WIN32'
+        cmd += ' -D_X86_ -DWIN32_VC -DWIN32 -D_WIN32'
         if GetTargetArch() == 'x64':
             cmd += ' -DWIN64_VC -DWIN64 -D_WIN64'
         # NOTE: this 1600 value is the version number for VC2010.
         cmd += ' -D_MSC_VER=1600 -D"__declspec(param)=" -D__cdecl -D_near -D_far -D__near -D__far -D__stdcall'
     if (COMPILER=="GCC"):
-        cmd += ' -D__inline -D__const=const -D__attribute__\(x\)='
+        cmd += ' -D__attribute__\(x\)='
         if GetTargetArch() in ("x86_64", "amd64"):
             cmd += ' -D_LP64'
         else:

Some files were not shown because too many files changed in this diff