[gcjx] Patch: FYI: more annotations work

Tom Tromey tromey@redhat.com
Sat Jan 22 07:56:00 GMT 2005


I'm checking this in on the gcjx branch.

This modifies how annotations are resolved, so that we don't get
incorrect circularity errors for meta-annotations.

It also fixes some bugs in reading and writing annotations.

Finally, there is an opportunistic fix for reading enums from class
files.

Annotations still can't really be tested as there is a circularity bug
when resolving a generic method in Enum.

Tom

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

	* bytecode/classwriter.cc (write): Don't set ACC_SUPER for enum
	classes.
	* model/annotype.cc (element_compatible_p): Resolve members
	before using annotation.
	* bytecode/attribute.cc (emit_annotation_value): Write enum
	constants.
	* model/memberref.cc (resolve): New method.
	(visit): New method.
	* bytecode/classreader.cc (parse_parameter_annotations): Set
	annotations on each parameter.
	(parse_annotation_value): Create a model_memberref_enum.
	(parse_self): Correctly handle ACC_SUPER when ACC_ENUM is set.
	* model/memberref.hh (class model_memberref_base): New class.
	(class model_memberref_forward): Derive from
	model_memberref_base.
	* model/variable.cc (resolve_classes): Use
	resolve_annotation_classes.
	(resolve): Call resolve_annotations.
	* model/method.cc (resolve_classes): Use
	resolve_annotation_classes.
	(resolve): Call resolve_annotations.
	* model/class.cc (do_resolve_classes): Use
	resolve_annotation_classes.
	(resolve_members): Call resolve_annotations.
	* model/iannotatable.cc (resolve_annotation_classes): New method.
	* model/iannotatable.hh (IAnnotatable::resolve_annotation_classes):
	Declare.	
	* model/annotation.cc (resolve_classes): New method.
	(resolve): Don't resolve 'name'.
	* model/annotation.hh (model_annotation::resolve): Documented.
	(model_annotation::resolve_classes): Declare.

Index: bytecode/attribute.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/attribute.cc,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 attribute.cc
--- bytecode/attribute.cc 19 Jan 2005 00:00:42 -0000 1.1.2.3
+++ bytecode/attribute.cc 22 Jan 2005 07:50:44 -0000
@@ -292,9 +292,25 @@
     }
   else
     {
-      // The only remaining case is an enum constant.
-      // FIXME: unwrap the member ref and write it.
-      abort ();
+      model_memberref_forward *b
+	= assert_cast<model_memberref_forward *> (expr);
+      expr = b->get_real ();
+      model_field_ref *fr = assert_cast<model_field_ref *> (expr);
+      model_field *fld = fr->get_field ();
+
+      // FIXME: what about inner classes here?
+      int type_index
+	= pool->add_utf (fld->get_declaring_class ()->get_descriptor ());
+      int name_index = pool->add_utf (fld->get_name ());
+
+      if (writer)
+	{
+	  writer->put ('e');
+	  writer->put2 (type_index);
+	  writer->put2 (name_index);
+	}
+
+      result += 5;
     }
 
   return result;
Index: bytecode/classreader.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/classreader.cc,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 classreader.cc
--- bytecode/classreader.cc 19 Jan 2005 19:49:11 -0000 1.1.2.5
+++ bytecode/classreader.cc 22 Jan 2005 07:50:45 -0000
@@ -160,8 +160,7 @@
 	ref_forwarding_type base = parse_field_descriptor (index);
 	uint16 fn_index = read_u2 ();
 	field_name = pool->get_utf8 (fn_index);
-	// FIXME.
-// 	val = new model_enum_field_ref (where, base, field_name);
+ 	val = new model_memberref_enum (where, base, field_name);
       }
       break;
 
@@ -239,9 +238,9 @@
     {
       std::list<ref_annotation> annotations;
       uint16 length = read_u2 ();
-      for (uint16 i = 0; i < length; ++i)
+      for (uint16 j = 0; j < length; ++j)
 	annotations.push_back (parse_annotation ());
-      // FIXME: do something with result
+      (*i)->set_annotations (annotations);
     }
 }
 
@@ -930,7 +929,12 @@
 	  result->set_superclass (super);
 	}
 
-      must_set |= ACC_SUPER;
+      // ACC_SUPER doesn't make sense for enums, but is required for
+      // ordinary classes.
+      if ((access_flags & ACC_ENUM) == 0)
+	must_set |= ACC_SUPER;
+      else
+	must_not_set |= ACC_SUPER;
       must_not_set |= ACC_ANNOTATION;
 
       if ((access_flags & ACC_ABSTRACT) != 0
Index: bytecode/classwriter.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/classwriter.cc,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 classwriter.cc
--- bytecode/classwriter.cc 17 Jan 2005 00:05:04 -0000 1.1.2.2
+++ bytecode/classwriter.cc 22 Jan 2005 07:50:45 -0000
@@ -319,7 +319,7 @@
   // only valid values are public and package-private.
   if ((mods & ACC_ACCESS) != 0 && (mods & ACC_ACCESS) != ACC_PUBLIC)
     mods &= ~ACC_ACCESS;
-  if (! the_class->interface_p ())
+  if (! the_class->interface_p () && ! the_class->enum_p ())
     {
       // This should be set by all modern compilers.
       mods |= ACC_SUPER;
Index: model/annotation.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/annotation.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 annotation.cc
--- model/annotation.cc 13 Jan 2005 03:18:35 -0000 1.1.2.1
+++ model/annotation.cc 22 Jan 2005 07:50:45 -0000
@@ -1,6 +1,6 @@
 // Represent an annotation.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -22,10 +22,20 @@
 #include "typedefs.hh"
 
 void
-model_annotation::resolve (resolution_scope *scope)
+model_annotation::resolve_classes (resolution_scope *scope)
 {
+  // FIXME: Resolution methods seem backwards on
+  // model_forwarding_type.
   name->resolve (scope);
+  // The reason we call set_type() here is that we need to know the
+  // annotation's type when handling SuppressWarnings.  This is
+  // moderately ugly.
+  set_type (name->type ());
+}
 
+void
+model_annotation::resolve (resolution_scope *scope)
+{
   if (! name->type ()->annotation_p ())
     throw name->error ("type %1 isn't an annotation type")
       % name;
@@ -35,8 +45,6 @@
   ::resolve (scope, args);
 
   anno_type->check_completeness (args, this);
-
-  set_type (anno_type);
 }
 
 void
Index: model/annotation.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/annotation.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 annotation.hh
--- model/annotation.hh 13 Jan 2005 03:18:35 -0000 1.1.2.1
+++ model/annotation.hh 22 Jan 2005 07:50:45 -0000
@@ -1,6 +1,6 @@
 // Represent an annotation.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -72,6 +72,13 @@
   {
   }
 
+  /// Resolve the "envelope" of this annotation.  This simply means
+  /// that the type of the annotation is determined.
+  void resolve_classes (resolution_scope *);
+
+  /// Fully resolve the annotation.  resolve_classes must have been
+  /// called first.  This will resolve all the arguments and then do
+  /// error checking.
   void resolve (resolution_scope *);
 
   void visit (visitor *);
Index: model/annotype.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/annotype.cc,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 annotype.cc
--- model/annotype.cc 19 Jan 2005 19:49:11 -0000 1.1.2.2
+++ model/annotype.cc 22 Jan 2005 07:50:45 -0000
@@ -136,6 +136,10 @@
 	}
       else
 	{
+	  // Make sure the (meta-)annotation expressions are all
+	  // resolved at this point.
+	  resolve_members ();
+
 	  model_annotation_value *val = targ->find_annotation ("value");
 	  assert (val);
 	  model_expression *expr = val->get_value ();
@@ -153,8 +157,8 @@
 	       ++i)
 	    {
 	      model_expression *e = (*i).get ();
-	      model_memberref_forward *b
-		= assert_cast<model_memberref_forward *> (e);
+	      model_memberref_base *b
+		= assert_cast<model_memberref_base *> (e);
 	      e = b->get_real ();
 	      model_field_ref *fr = assert_cast<model_field_ref *> (e);
 
Index: model/class.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/class.cc,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 class.cc
--- model/class.cc 19 Jan 2005 02:11:07 -0000 1.1.2.3
+++ model/class.cc 22 Jan 2005 07:50:46 -0000
@@ -1059,7 +1059,7 @@
 
   resolve_hook (scope);
 
-  resolve_annotations (scope);
+  resolve_annotation_classes (scope);
 
   // Put the type parameters in scope.  Note that we don't resolve
   // them here, as that can lead to false circularity reports.
@@ -1307,6 +1307,8 @@
   if (! superclass && ! interface)
     compute_object_interface_methods ();
 
+  resolve_annotations (scope);
+
   // Let the subclass modify behavior a little.  This must come after
   // compute_object_interface_methods().
   resolve_member_hook (scope);
Index: model/iannotatable.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/iannotatable.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 iannotatable.cc
--- model/iannotatable.cc 13 Jan 2005 03:18:36 -0000 1.1.2.1
+++ model/iannotatable.cc 22 Jan 2005 07:50:46 -0000
@@ -1,6 +1,6 @@
 // Represent an annotatable object.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -35,6 +35,12 @@
 }
 
 void
+IAnnotatable::resolve_annotation_classes (resolution_scope *scope)
+{
+  ::resolve_classes (scope, annotations);
+}
+
+void
 IAnnotatable::resolve_annotations (resolution_scope *scope)
 {
   ::resolve (scope, annotations);
Index: model/iannotatable.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/iannotatable.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 iannotatable.hh
--- model/iannotatable.hh 13 Jan 2005 03:18:36 -0000 1.1.2.1
+++ model/iannotatable.hh 22 Jan 2005 07:50:46 -0000
@@ -1,6 +1,6 @@
 // Represent an annotatable object.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -45,6 +45,9 @@
 
   virtual annotation_kind get_annotation_kind () const = 0;
 
+  /// Resolve the envelope of the annotations.
+  void resolve_annotation_classes (resolution_scope *);
+
   /// Subclasses should call this when they are resolved in order to
   /// resolve their annotations as well.
   void resolve_annotations (resolution_scope *);
Index: model/memberref.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/memberref.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 memberref.cc
--- model/memberref.cc 13 Jan 2005 03:18:36 -0000 1.1.2.1
+++ model/memberref.cc 22 Jan 2005 07:50:46 -0000
@@ -1,6 +1,6 @@
 // Member references.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -50,3 +50,35 @@
   real->resolve (scope);
   set_type (real->type ());
 }
+
+void
+model_memberref_enum::resolve (resolution_scope *scope)
+{
+  base_type->resolve (scope);
+  if (! base_type->type ()->enum_p ())
+    throw error ("type %1 not an %<enum%>") % base_type->type ();
+
+  model_class *klass = assert_cast<model_class *> (base_type->type ());
+  std::set<model_field *> result;
+  klass->find_members (field_name, result, scope->get_current_class (), NULL);
+  if (result.empty ())
+    throw error ("no %<enum%> constant named %1 in %2")
+      % field_name % klass;
+  else if (result.size () > 1)
+    throw error ("ambiguous reference to %<enum%> constant named %1 in %2")
+      % field_name % klass;
+
+  ref_field_ref rf = new model_field_ref (get_location ());
+  rf->set_field (field_name);
+  rf->set_field (*(result.begin ()));
+
+  real = rf;
+  set_type (klass);
+}
+
+void
+model_memberref_enum::visit (visitor *)
+{
+  // Not needed.
+  abort ();
+}
Index: model/memberref.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/memberref.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 memberref.hh
--- model/memberref.hh 13 Jan 2005 03:18:36 -0000 1.1.2.1
+++ model/memberref.hh 22 Jan 2005 07:50:46 -0000
@@ -1,6 +1,6 @@
 // Member references.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -22,19 +22,39 @@
 #ifndef GCJX_MODEL_MEMBERREF_HH
 #define GCJX_MODEL_MEMBERREF_HH
 
-// When parsing something like "a.b.c.d" or "a.b.c.d()", we won't know
-// until the analysis phase what we're looking at.  For instance, "a"
-// might be a variable or a type, and likewise for the other elements.
-// This class represents an undetermined expression like the above.
-// It can also represent a simple variable reference.
-class model_memberref_forward : public model_expression
+/// The base class for all kinds of deferred member references.
+class model_memberref_base : public model_expression
 {
-  // The unresolved identifier sequence.
-  std::list<std::string> ids;
+protected:
 
   // The member reference to which we forward requests.
   ref_expression real;
 
+  model_memberref_base (const location &w)
+    : model_expression (w)
+  {
+  }
+
+public:
+
+  // This is sort of ugly, see unary.cc to see its use.
+  // FIXME.
+  model_expression *get_real ()
+  {
+    return real.get ();
+  }
+};
+
+/// When parsing something like "a.b.c.d" or "a.b.c.d()", we won't know
+/// until the analysis phase what we're looking at.  For instance, "a"
+/// might be a variable or a type, and likewise for the other elements.
+/// This class represents an undetermined expression like the above.
+/// It can also represent a simple variable reference.
+class model_memberref_forward : public model_memberref_base
+{
+  // The unresolved identifier sequence.
+  std::list<std::string> ids;
+
   // True if a method call.
   bool is_call;
 
@@ -55,7 +75,7 @@
 
   // This constructor is used by the generic template subclass.
   model_memberref_forward (const location &w)
-    : model_expression (w),
+    : model_memberref_base (w),
       is_call (false),
       is_lhs (false),
       is_compound (false)
@@ -65,7 +85,7 @@
 public:
 
   model_memberref_forward (const location &w, const std::list<std::string> &l)
-    : model_expression (w),
+    : model_memberref_base (w),
       ids (l),
       is_call (false),
       is_lhs (false),
@@ -101,13 +121,6 @@
     return real->string_value ();
   }
 
-  // This is sort of ugly, see unary.cc to see its use.
-  // FIXME.
-  model_expression *get_real ()
-  {
-    return real.get ();
-  }
-
   /// Return true if this is a reference to a method call.
   bool call_p () const
   {
@@ -121,4 +134,35 @@
   }
 };
 
+/// This form of a deferred member reference is used only when reading
+/// an enum constant reference from a class file.
+class model_memberref_enum : public model_memberref_base
+{
+  // The enum class.
+  ref_forwarding_type base_type;
+
+  // The name of the enum constant.
+  std::string field_name;
+
+  bool compute_constant_p ()
+  {
+    return false;
+  }
+
+public:
+
+  model_memberref_enum (const location &w,
+			const ref_forwarding_type &base,
+			const std::string &fn)
+    : model_memberref_base (w),
+      base_type (base),
+      field_name (fn)
+  {
+  }
+
+  void resolve (resolution_scope *);
+
+  void visit (visitor *);
+};
+
 #endif // GCJX_MODEL_MEMBERREF_HH
Index: model/method.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/method.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 method.cc
--- model/method.cc 13 Jan 2005 03:18:36 -0000 1.1.2.1
+++ model/method.cc 22 Jan 2005 07:50:46 -0000
@@ -1,6 +1,6 @@
 // Methods.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -536,6 +536,8 @@
 void
 model_method::resolve (resolution_scope *scope)
 {
+  resolve_annotations (scope);
+
   resolution_scope::push_warnings warn_holder (scope, this);
 
   // Push the type parameters.
@@ -618,7 +620,7 @@
 {
   // Resolve annotations here since they seem like part of the
   // envelope.
-  resolve_annotations (scope);
+  resolve_annotation_classes (scope);
 
   resolution_scope::push_warnings warn_holder (scope, this);
 
Index: model/variable.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/variable.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 variable.cc
--- model/variable.cc 13 Jan 2005 03:18:36 -0000 1.1.2.1
+++ model/variable.cc 22 Jan 2005 07:50:46 -0000
@@ -1,6 +1,6 @@
 // Represent a variable.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -25,12 +25,13 @@
 model_variable_decl::resolve_classes (resolution_scope *scope)
 {
   decltype->resolve (scope);
-  resolve_annotations (scope);
+  resolve_annotation_classes (scope);
 }
 
 void
 model_variable_decl::resolve (resolution_scope *scope)
 {
+  resolve_annotations (scope);
   decltype->resolve (scope);  // fixme redundant for fields...
   if (initializer)
     {



More information about the Java-patches mailing list