home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / mnl-rpc++-2.3.1 / part01 / gcc-2.2.fix < prev    next >
Encoding:
Internet Message Format  |  1993-04-24  |  8.4 KB

  1. To: bug-g++@prep.ai.mit.edu
  2. Subject: gcc-2.2 loops with template-local typedefs (bug&patch)
  3. BCC: mnl,ulf
  4. --text follows this line--
  5. Hi,
  6.  
  7. trying to translate the following fragment on a Sparc running SunOs 4.1.2
  8. with gcc-2.2 results in gcc infinitly looping.
  9.  
  10. ---------------------------------------------------------------------------
  11. // -*- c++ -*-
  12.  
  13. class AnyRpcCallback
  14. {
  15. protected:
  16.  
  17. public:
  18.   inline virtual ~AnyRpcCallback () {}
  19.   inline virtual void Do (void* in, void* out) = 0;
  20. };
  21.  
  22. template<class T> class RpcCallback : public AnyRpcCallback
  23. {
  24.   typedef void (T::*Method)(void*, void*);
  25.   typedef void (T::*MethodN)(void*, void**);
  26.   typedef void (T::*Method1)(void*, void*);
  27.   typedef void (T::*Method2)(void*, void*, void*);
  28.  
  29. private:
  30.   T* object;
  31.   void (T::*method)(void*, void*);
  32.  
  33. public:
  34.   inline RpcCallback (T* o, void* m)
  35.     { object = o; method = m; }
  36.   inline void Do (void* in, void* out)
  37.     { (object->*method)(in, out); }
  38. };
  39.  
  40. class Test
  41. {
  42. public:
  43.   void m (void*, void*);
  44. };
  45.  
  46. main ()
  47. {
  48.   Test o;
  49.   AnyRpcCallback* cb = new RpcCallback<Test> (&o, &Test::m);
  50. }
  51. ---------------------------------------------------------------------------
  52.  
  53. PLEASE NOTE that you will get another loop due to a bug that I have
  54. reported together with a patch earlier (it's appended to this mail).
  55. So you won't be able to reproduce the bug reported in this mail unless
  56. you have my previous patch applied. I am, however, definitely sure
  57. (and the explanation below will confirm it) that the bug reported in
  58. this mail is *NOT* caused by my patch!
  59.  
  60. The problem is, that the "chain" field of the tree-nodes used by gcc
  61. for its internal representation is used for various purposes, and in
  62. the case of this template-local typedef, someone lost track of its usage.
  63.  
  64. After parsing, the TYPE_DECL-node created for the typedef is appended
  65. to the scope via "pushlevel". Types in the current scope are linked
  66. using the "chain" field. At the same time, however, all components of
  67. the template are linked together during parsing using the same "chain"
  68. field. Parsing the second typedef, "pushlevel" makes the first typedef
  69. a successor of the second typedef and the subsequent catenation of
  70. components makes the second typedef a successor of the first typedef
  71. thus creating a loop.
  72.  
  73. The resulting list of all components is used in routine
  74. "finish_struct".
  75.  
  76. I think the most proper approach would be to use TREE_LIST nodes in
  77. the list of components as indirect references to the typedef-nodes.
  78. This is easy to achieve, it is, however, very hard to modify
  79. finish_struct in a way that it handles these indirection properly.
  80. Actually, I gave up when I tried to understand & modify the routine
  81. that removes the duplicate declarations from the list of components.
  82.  
  83. There are two easier approaches: (1) Don't include typedefs in the
  84. list of components, (2) use copies of the typedef-node which have an
  85. unused chain field. The first approach assumes that finish_struct
  86. doesn't do anything with typedefs, so it wouldn't be important if they
  87. are missing from the list of components. If this is the case, however,
  88. it can't hurt to use copies of the typedef-nodes (copies of the
  89. originals that are linked in the scope-list), so the second approach
  90. is safer. It can only fail if finish_struct modifies the typedef-nodes
  91. and this modification is significant for the typedef-nodes in the
  92. scope-list (which are, of course, not modified. Only the copies are).
  93.  
  94. So I think the patch is pretty safe. It fixes the problem and doesn't
  95. seem to introduce new ones. I'm aware that typedefs that are local to
  96. templates stretch language features to the limits, but it makes my
  97. C++ interface to RPCs real nice (I'll post it one of these days).
  98.  
  99. Michael
  100.  
  101. *** .orig/cp-parse.y    Mon Jun 15 17:08:58 1992
  102. --- cp-parse.y    Mon Jun 15 19:13:15 1992
  103. ***************
  104. *** 2211,2217 ****
  105.                 if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
  106.               $$ = grok_enum_decls (t, $2);
  107.                 else
  108. !             $$ = $2;
  109.               }
  110.             end_exception_decls ();
  111.           }
  112. --- 2211,2233 ----
  113.                 if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
  114.               $$ = grok_enum_decls (t, $2);
  115.                 else
  116. !             {
  117. !               /* if a component is a typedef, it is inserted
  118. !                  in the list of nodes that make up the valid
  119. !                  types in the scope. Thus its chain field is
  120. !                  used and can't be used a second time for linking
  121. !                  the components of the struct. So, we make a copy
  122. !                  here. This apparently works. The proper thing
  123. !                  to do, however, would be to use a TREE_LIST
  124. !                  node to reference the typedef. I tried to rewrite
  125. !                  finish_struct accordingly (i.e., ``dereference''
  126. !                  components TREE_LIST before use, but I gave up.
  127. !                  mnl@dtro.e-technik.th-darmstadt.de */
  128. !               if (TREE_CODE ($2) == TYPE_DECL)
  129. !                 $$ = copy_node ($2);
  130. !               else
  131. !                 $$ = $2;
  132. !             }
  133.               }
  134.             end_exception_decls ();
  135.           }
  136.  
  137. ===========================================================================
  138. The previous bug:
  139. ---------------------------------------------------------------------------
  140. Return-Path: <mnl>
  141. Date: Wed, 10 Jun 92 19:31:13 +0200
  142. From: "Michael N. Lipp" <mnl>
  143. To: bug-g++@prep.ai.mit.edu
  144. Subject: gcc-2.2 bug&patch: typedef in template
  145.  
  146. Hi,
  147.  
  148. gcc-2.2 on a sparc running SunOS 4.1.2 enters an infinite loop when
  149. compiling this:
  150.  
  151. -----------------------------------------------------------------------------
  152. // -*- c++ -*-
  153.  
  154. class AnyRpcCallback
  155. {
  156. protected:
  157.  
  158. public:
  159.   inline virtual ~AnyRpcCallback () {}
  160.   inline virtual void Do (void* in, void* out) = 0;
  161. };
  162.  
  163. template<class T> class RpcCallback : public AnyRpcCallback
  164. {
  165.   typedef void (T::*Method)(void*, void*);
  166.  
  167. private:
  168.   T* object;
  169.   void (T::*method)(void*, void*);
  170.  
  171. public:
  172.   inline RpcCallback (T* o, void* m)
  173.     { object = o; method = m; }
  174.   inline void Do (void* in, void* out)
  175.     { (object->*method)(in, out); }
  176. };
  177.  
  178. class Test
  179. {
  180. public:
  181.   void m (void*, void*);
  182. };
  183.  
  184. main ()
  185. {
  186.   Test o;
  187.   AnyRpcCallback* cb = new RpcCallback<Test> (&o, &Test::m);
  188. }
  189. -----------------------------------------------------------------------------
  190.  
  191. This is quite an improvement over gcc-2.1 which dumped core with this
  192. source.
  193.  
  194. I tracked the cause down: grokdeclarator does a pushlevel(0), then
  195. calls start_decl, which in turn calls grokdeclarator again which does
  196. a poplevel_class. This poplevel_class pops the level pushed by
  197. pushlevel(0) and so the poplevel performed by grokdeclarator to match
  198. its pushlevel(0) pops quite a different level! This can easily be
  199. observed by compiling cp-decl.c with -DDEBUG_CP_BINDING_LEVELS.
  200.  
  201. Here is a patch that fixes the bug. I don't think it hits the real
  202. cause of this problem, but it works.
  203.  
  204. *** .orig/cp-decl.c    Wed Jun 10 14:06:26 1992
  205. --- cp-decl.c    Wed Jun 10 15:20:38 1992
  206. ***************
  207. *** 6874,6882 ****
  208. --- 6874,6889 ----
  209.         tree loc_typedecl;
  210.         register int i = sizeof (struct lang_decl_flags) / sizeof (int);
  211.         register int *pi;
  212. +       struct binding_level *local_binding_level;
  213.   
  214.         /* keep `grokdeclarator' from thinking we are in PARM context.  */
  215.         pushlevel (0);
  216. +       /* poplevel_class may be called by grokdeclarator which is called in
  217. +          start_decl which is called below. In this case, our pushed level
  218. +          may vanish and poplevel mustn't be called. So remember what we
  219. +          have pushed and pop only if that is matched by 
  220. +          current_binding_level later. mnl@dtro.e-technik.th-darmstadt.de */
  221. +       local_binding_level = current_binding_level;
  222.         loc_typedecl = start_decl (declarator, declspecs, initialized, NULL_TREE);
  223.   
  224.         pi = (int *) permalloc (sizeof (struct lang_decl_flags));
  225. ***************
  226. *** 6883,6889 ****
  227.         while (i > 0)
  228.           pi[--i] = 0;
  229.         DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi;
  230. !       poplevel (0, 0, 0);
  231.   
  232.   #if 0
  233.         if (TREE_CODE (TREE_TYPE (loc_typedecl)) == ENUMERAL_TYPE)
  234. --- 6890,6897 ----
  235.         while (i > 0)
  236.           pi[--i] = 0;
  237.         DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi;
  238. !       if (current_binding_level == local_binding_level)
  239. !         poplevel (0, 0, 0);
  240.   
  241.   #if 0
  242.         if (TREE_CODE (TREE_TYPE (loc_typedecl)) == ENUMERAL_TYPE)
  243.  
  244. Michael
  245.  
  246. -----------------,------------------------------,------------------------------
  247. Michael N. Lipp  !  Institut fuer Datentechnik  !  Phone: 49-6151-163776
  248.                  !  Merckstr. 25     ,----------'  Fax:   49-6151-164976
  249.                  !  D-6100 Darmstadt ! E-Mail:
  250.                  !  (Germany)        !     mnl@dtro.e-technik.th-darmstadt.de
  251. -----------------'-------------------'-----------------------------------------
  252.  
  253.