Browse Source

Fix some edge cases for preprocessor, support auto keyword, MSVC compile fix

rdb 10 years ago
parent
commit
155ae811aa

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


+ 9 - 1
dtool/src/cppparser/cppBison.yxx

@@ -1723,6 +1723,10 @@ type:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_AUTO
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_auto);
 }
         ;
 
@@ -1813,6 +1817,10 @@ type_decl:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_AUTO
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_auto);
 }
         ;
 
@@ -2114,7 +2122,7 @@ namespace_declaration:
   }
 
   CPPNamespace *nspace = new CPPNamespace($3, scope, @2.file);
-  nspace->_inline = true;
+  nspace->_is_inline = true;
   current_scope->add_declaration(nspace, global_scope, current_lexer, @2);
   current_scope->define_namespace(nspace);
   push_scope(scope);

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

@@ -189,7 +189,7 @@ get_local_name(CPPScope *scope) const {
 
     // Strip off template scopes, since they don't add anything
     // particularly meaningful to the local name.
-    while (my_scope->as_template_scope() != NULL) {
+    while (my_scope != NULL && my_scope->as_template_scope() != NULL) {
       my_scope = my_scope->get_parent_scope();
     }
 

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

@@ -28,7 +28,7 @@ CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file) :
   CPPDeclaration(file),
   _ident(ident),
   _scope(scope),
-  _inline(false)
+  _is_inline(false)
 {
 }
 
@@ -88,7 +88,7 @@ get_scope() const {
 ////////////////////////////////////////////////////////////////////
 void CPPNamespace::
 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
-  if (_inline) {
+  if (_is_inline) {
     out << "inline ";
   }
   if (!complete && _ident != NULL) {

+ 3 - 1
dtool/src/cppparser/cppNamespace.h

@@ -42,7 +42,9 @@ public:
 
   virtual CPPNamespace *as_namespace();
 
-  bool _inline;
+  // We can't call this _inline since that would clash with an MSVC
+  // built-in keyword declaration.
+  bool _is_inline;
 
 private:
   CPPIdentifier *_ident;

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

@@ -72,7 +72,8 @@ parse_file(const Filename &filename) {
 ////////////////////////////////////////////////////////////////////
 CPPExpression *CPPParser::
 parse_expr(const string &expr) {
-  return CPPPreprocessor::parse_expr(expr, this, this);
+  YYLTYPE loc = {};
+  return CPPPreprocessor::parse_expr(expr, this, this, loc);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 29 - 13
dtool/src/cppparser/cppPreprocessor.cxx

@@ -774,6 +774,7 @@ push_file(const CPPFile &file) {
     indent(cerr, _files.size() * 2)
       << "Reading " << file << "\n";
   }
+  assert(_last_c == 0);
 
   _files.push_back(InputFile());
   InputFile &infile = _files.back();
@@ -841,7 +842,8 @@ push_string(const string &input, bool lock_position) {
 //               string and return the new string.
 ////////////////////////////////////////////////////////////////////
 string CPPPreprocessor::
-expand_manifests(const string &input_expr, bool expand_undefined) {
+expand_manifests(const string &input_expr, bool expand_undefined,
+                 const YYLTYPE &loc) {
   // Get a copy of the expression string we can modify.
   string expr = input_expr;
 
@@ -872,11 +874,28 @@ expand_manifests(const string &input_expr, bool expand_undefined) {
             manifest_found = true;
 
           } else if (expand_undefined && ident != "true" && ident != "false") {
-            // It is not found.  Expand it to 0.
+            // It is not found.  Expand it to 0, but only if we are currently
+            // parsing an #if expression.
             expr = expr.substr(0, q) + "0" + expr.substr(p);
             p = q + 1;
           }
         }
+      } else if (expr[p] == '\'' || expr[p] == '"') {
+        // Skip the next part until we find a closing quotation mark.
+        char quote = expr[p];
+        p++;
+        while (p < expr.size() && expr[p] != quote) {
+          if (expr[p] == '\\') {
+            // This might be an escaped quote.  Skip an extra char.
+            p++;
+          }
+          p++;
+        }
+        if (p >= expr.size()) {
+          // Unclosed string.
+          warning("missing terminating " + string(1, quote) + " character", loc);
+        }
+        p++;
       } else {
         p++;
       }
@@ -903,8 +922,8 @@ expand_manifests(const string &input_expr, bool expand_undefined) {
 ////////////////////////////////////////////////////////////////////
 CPPExpression *CPPPreprocessor::
 parse_expr(const string &input_expr, CPPScope *current_scope,
-           CPPScope *global_scope) {
-  string expr = expand_manifests(input_expr, false);
+           CPPScope *global_scope, const YYLTYPE &loc) {
+  string expr = expand_manifests(input_expr, false, loc);
 
   CPPExpressionParser ep(current_scope, global_scope);
   ep._verbose = 0;
@@ -1475,7 +1494,7 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
     if (!manifest->_has_parameters) {
       string expr_string = manifest->expand();
       if (!expr_string.empty()) {
-        manifest->_expr = parse_expr(expr_string, global_scope, global_scope);
+        manifest->_expr = parse_expr(expr_string, global_scope, global_scope, loc);
       }
     }
 
@@ -1554,7 +1573,7 @@ void CPPPreprocessor::
 handle_if_directive(const string &args, const YYLTYPE &loc) {
   // When expanding manifests, we should replace unknown macros
   // with 0.
-  string expr = expand_manifests(args, true);
+  string expr = expand_manifests(args, true, loc);
 
   int expression_result = 0;
   CPPExpressionParser ep(current_scope, global_scope);
@@ -1602,7 +1621,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
   // 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 (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) {
-    expr = expand_manifests(expr, false);
+    expr = expand_manifests(expr, false, loc);
   }
 
   if (!expr.empty()) {
@@ -2727,14 +2746,11 @@ get() {
     indent(cerr, _files.size() * 2)
       << "End of input stream, restoring to previous input\n";
 #endif
-    int last_c = _files.back()._prev_last_c;
     _files.pop_back();
 
-    if (last_c != '\0') {
-      c = last_c;
-    } else if (!_files.empty()) {
-      c = _files.back().get();
-    }
+    // Synthesize a newline, just in case the file doesn't already
+    // end with one.
+    c = '\n';
   }
 
   if (c == '\n') {

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

@@ -111,9 +111,10 @@ protected:
   bool push_file(const CPPFile &file);
   bool push_string(const string &input, bool lock_position);
 
-  string expand_manifests(const string &input_expr, bool expand_undefined);
+  string expand_manifests(const string &input_expr, bool expand_undefined,
+                          const YYLTYPE &loc);
   CPPExpression *parse_expr(const string &expr, CPPScope *current_scope,
-                            CPPScope *global_scope);
+                            CPPScope *global_scope, const YYLTYPE &loc);
 
 private:
   CPPToken internal_get_next_token();

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

@@ -297,7 +297,7 @@ define_namespace(CPPNamespace *ns) {
 
   _namespaces[name] = ns;
 
-  if (ns->_inline) {
+  if (ns->_is_inline) {
     // Add an implicit using declaration for an inline namespace.
     _using.insert(ns->get_scope());
   }

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

@@ -158,6 +158,10 @@ output(ostream &out, int, CPPScope *, bool) const {
     out << "parameter";
     break;
 
+  case T_auto:
+    out << "auto";
+    break;
+
   default:
     out << "***invalid type***";
   }

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

@@ -55,6 +55,13 @@ public:
     // but it initially looks like a function prototype.
     //
     T_parameter,
+
+    // T_auto is also a special type that corresponds to the "auto"
+    // keyword used in a variable assignment.  The type of it is
+    // automatically determined at a later stage based on the type
+    // of the expression that is assigned to it.
+    //
+    T_auto,
   };
 
   enum Flags {

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