This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gcjx] Patch: FYI:


I'm checking this in on the gcjx branch.

This adds the C++ keyword clash hack to the gcjx CNI header generator.
It also fixes a virtual method buglet in the CNI generator.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* header/cni.hh (cni_code_generator::write_field): Updated.
	(cni_code_generator::keyword_p): Declare.
	* header/cni.cc (keywords): New global.
	(NUM_KEYWORDS): New define.
	(keyword_p): New method.
	(generate): Compute method names.
	(write_field): Added 'method_names' arguments.  Handle C++ keyword
	clash.
	(write_method): Handle C++ keyword clash.  Skip synthetic
	methods.
	* header/cni.cc (write_method): Mark more methods as virtual.

Index: header/cni.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/header/Attic/cni.cc,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 cni.cc
--- header/cni.cc 17 Apr 2005 18:33:54 -0000 1.1.2.4
+++ header/cni.cc 17 Apr 2005 18:40:39 -0000
@@ -24,6 +24,90 @@
 
 #include <fstream>
 
+// Sorted list of C++ keywords.
+// FIXME: doesn't include some things that G++ might consider as
+// keywords.
+static const char *const keywords[] =
+{
+  "and",
+  "and_eq",
+  "asm",
+  "auto",
+  "bitand",
+  "bitor",
+  "bool",
+  "break",
+  "case",
+  "catch",
+  "char",
+  "class",
+  "compl",
+  "const",
+  "const_cast",
+  "continue",
+  "default",
+  "delete",
+  "do",
+  "double",
+  "dynamic_cast",
+  "else",
+  "enum",
+  "explicit",
+  "export",
+  "extern",
+  "false",
+  "float",
+  "for",
+  "friend",
+  "goto",
+  "if",
+  "inline",
+  "int",
+  "long",
+  "mutable",
+  "namespace",
+  "new",
+  "not",
+  "not_eq",
+  "operator",
+  "or",
+  "or_eq",
+  "private",
+  "protected",
+  "public",
+  "register",
+  "reinterpret_cast",
+  "return",
+  "short",
+  "signed",
+  "sizeof",
+  "static",
+  "static_cast",
+  "struct",
+  "switch",
+  "template",
+  "this",      
+  "throw",
+  "true",
+  "try",
+  "typedef",
+  "typeid",
+  "typename",
+  "typeof",
+  "union",
+  "unsigned",
+  "using",
+  "virtual",
+  "void",
+  "volatile",
+  "wchar_t",
+  "while",
+  "xor",
+  "xor_eq"
+};
+
+#define NUM_KEYWORDS  (sizeof (keywords) / sizeof (keywords[0]))
+
 cni_code_generator::cni_code_generator (compiler *c, directory_cache &dirs)
   : code_generator (dirs),
     comp (c),
@@ -31,6 +115,37 @@
 {
 }
 
+bool
+cni_code_generator::keyword_p (const std::string &name)
+{
+  // Strip '$'s off the end.
+  int i;
+  for (i = name.length () - 1; i >= 0 && name[i] == '$'; --i)
+    ;
+  std::string newname = name.substr (0, i + 1);
+
+  int low = 0;
+  int high = NUM_KEYWORDS;
+  int last = -1;
+
+  while (true)
+    {
+      int current = (low + high) / 2;
+      if (current == last)
+	break;
+      int cmp = newname.compare (keywords[current]);
+      if (cmp == 0)
+	return true;
+      else if (cmp > 0)
+	low = current;
+      else
+	high = current;
+      last = current;
+    }
+
+  return false;
+}
+
 void
 cni_code_generator::emit_actions (std::ostream &out,
 				  cni_code_generator::action what,
@@ -329,7 +444,8 @@
 				  model_method *meth,
 				  modifier_t &current_flags)
 {
-  if (meth->instance_initializer_p () || meth->static_initializer_p ())
+  if (meth->instance_initializer_p () || meth->static_initializer_p ()
+      || (meth->get_modifiers () & ACC_SYNTHETIC) != 0)
     return;
 
   modifier_t new_flags = meth->get_modifiers () & ACC_ACCESS;
@@ -351,14 +467,19 @@
     {
       if (meth->static_p ())
 	out << "static ";
-      else if (! ((meth->get_modifiers () & (ACC_FINAL | ACC_PRIVATE)) != 0
-		  || ((meth->get_declaring_class ()->get_modifiers ()
-		       & ACC_FINAL) != 0)))
+      // Private methods don't get a vtable entry, but others do.
+      // Interestingly, this makes CNI less efficient than the Java
+      // C++ ABI in one case: calls to methods in a final class.
+      // FIXME: decisions like this should be handled in a single
+      // place, right now this logic is duplicated elsewhere.
+      else if ((meth->get_modifiers () & ACC_PRIVATE) == 0)
 	out << "virtual ";
       out << cxxname (meth->get_return_type ());
       if (! meth->get_return_type ()->reference_p ())
 	out << " ";
       out << meth->get_name ();
+      if (keyword_p (meth->get_name ()))
+	out << "$";
     }
   out << " (";
 
@@ -384,7 +505,8 @@
 cni_code_generator::write_field (std::ostream &out,
 				 model_field *field,
 				 modifier_t &current_flags,
-				 bool &is_first)
+				 bool &is_first,
+				 const std::set<std::string> &method_names)
 {
   modifier_t new_flags = field->get_modifiers () & ACC_ACCESS;
   update_modifiers (out, new_flags, current_flags);
@@ -404,7 +526,13 @@
 	  << ")))) ";
     }
 
-  out << field->get_name () << ";" << std::endl;
+  out << field->get_name ();
+  if (method_names.find (field->get_name ()) != method_names.end ())
+    out << "__";
+  else if (keyword_p (field->get_name ()))
+    out << "$";
+
+  out << ";" << std::endl;
 }
 
 void
@@ -473,6 +601,7 @@
 
   modifier_t current_flags = 0;
 
+  std::set<std::string> method_names;
   AllMethodsIterator end = klass->end_all_methods ();
   for (AllMethodsIterator i = klass->begin_all_methods ();
        i != end;
@@ -488,13 +617,14 @@
 	  && ! (*i)->get_declaring_class ()->interface_p ())
 	continue;
       write_method (out, (*i).get (), current_flags);
+      method_names.insert ((*i)->get_name ());
     }
 
   bool first = true;
   for (std::list<ref_field>::const_iterator i = fields.begin ();
        i != fields.end ();
        ++i)
-    write_field (out, (*i).get (), current_flags, first);
+    write_field (out, (*i).get (), current_flags, first, method_names);
 
   // One final phony field.
   update_modifiers (out, modifier_t (ACC_PUBLIC), current_flags);
Index: header/cni.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/header/Attic/cni.hh,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 cni.hh
--- header/cni.hh 17 Apr 2005 18:33:54 -0000 1.1.2.5
+++ header/cni.hh 17 Apr 2005 18:40:39 -0000
@@ -57,6 +57,7 @@
   // True if we should emit headers for Object and Class.
   bool std_headers_ok;
 
+  bool keyword_p (const std::string &);
   std::string cxxname (model_type *, bool = true);
   void update_modifiers (std::ostream &, modifier_t, modifier_t &);
   void add (model_type *, std::set<model_class *> &,
@@ -66,7 +67,8 @@
 		       const method_iterator &, const method_iterator &,
 		       const std::list<ref_field> &);
   void write_method (std::ostream &, model_method *, modifier_t &);
-  void write_field (std::ostream &, model_field *, modifier_t &, bool &);
+  void write_field (std::ostream &, model_field *, modifier_t &, bool &,
+		    const std::set<std::string> &);
 
   void indent (std::ostream &, int);
   void open_package (std::ostream &, model_package *, model_package *, int &);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]