home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / gnu / g / bug / 2109 < prev    next >
Encoding:
Text File  |  1993-01-02  |  8.4 KB  |  253 lines

  1. Newsgroups: gnu.g++.bug
  2. Path: sparky!uunet!cis.ohio-state.edu!dtro.e-technik.TH-darmstadt.DE!mnl
  3. From: mnl@dtro.e-technik.TH-darmstadt.DE (Michael N. Lipp)
  4. Subject: Two template bugs
  5. Message-ID: <MNL.93Jan2153336@mnlsun.dtro.e-technik.th-darmstadt.de>
  6. Sender: gnulists@ai.mit.edu
  7. Organization: TH-Darmstadt
  8. Distribution: gnu
  9. Date: Sat, 2 Jan 1993 15:33:36 GMT
  10. Approved: bug-g++@prep.ai.mit.edu
  11. Lines: 240
  12.  
  13. There are two bugs in gcc-2.3.3 that I have reported together with
  14. fixes for gcc-2.2.2 previously.  The first bug is commented now (but
  15. not fixed), the second isn't fixed either (I can understand that.  It
  16. is hard to do it properly).  I'm repeating the bug report below
  17. together with new context diffs.  Please note that I have not
  18. re-debugged, I have simply found that the same patches make things
  19. work.  So maybe the comments are out of date.
  20.  
  21. Bug1:
  22.  
  23. Compiling this
  24. --------------------------------------------------
  25. // -*- c++ -*-
  26.  
  27. class AnyRpcCallback
  28. {
  29. protected:
  30.  
  31. public:
  32.   inline virtual ~AnyRpcCallback () {}
  33.   inline virtual void Do (void* in, void* out) = 0;
  34. };
  35.  
  36. template<class T> class RpcCallback : public AnyRpcCallback
  37. {
  38.   typedef void (T::*Method)(void*, void*);
  39.  
  40. private:
  41.   T* object;
  42.   void (T::*method)(void*, void*);
  43.  
  44. public:
  45.   inline RpcCallback (T* o, void* m)
  46.     { object = o; method = m; }
  47.   inline void Do (void* in, void* out)
  48.     { (object->*method)(in, out); }
  49. };
  50.  
  51. class Test
  52. {
  53. public:
  54.   void m (void*, void*);
  55. };
  56.  
  57. void Test::m (void*, void*)
  58. {
  59. }
  60.  
  61. main ()
  62. {
  63.   Test o;
  64.   AnyRpcCallback* cb = new RpcCallback<Test> (&o, &Test::m);
  65. }
  66. --------------------------------------------------
  67. results in cc1plus looping infinitely.
  68.  
  69. I tracked the cause down: grokdeclarator does a pushlevel(0), then
  70. calls start_decl, which in turn calls grokdeclarator again which does
  71. a poplevel_class. This poplevel_class pops the level pushed by
  72. pushlevel(0) and so the poplevel performed by grokdeclarator to match
  73. its pushlevel(0) pops quite a different level! This can easily be
  74. observed by compiling cp-decl.c with -DDEBUG_CP_BINDING_LEVELS.
  75.  
  76. In gcc-2.3.3 the problem seems to be known as it is commented.
  77.  
  78. Here is a patch that fixes the bug. I don't think it hits the real
  79. cause of this problem, but it works.
  80.  
  81. *** cp-decl.c.orig    Sat Jan  2 15:04:20 1993
  82. --- cp-decl.c    Sat Jan  2 15:06:18 1993
  83. ***************
  84. *** 7245,7253 ****
  85. --- 7245,7260 ----
  86.         tree loc_typedecl;
  87.         register int i = sizeof (struct lang_decl_flags) / sizeof (int);
  88.         register int *pi;
  89. +        struct binding_level *local_binding_level;
  90.   
  91.         /* keep `grokdeclarator' from thinking we are in PARM context.  */
  92.         pushlevel (0);
  93. +        /* poplevel_class may be called by grokdeclarator which is called in
  94. +           start_decl which is called below. In this case, our pushed level
  95. +           may vanish and poplevel mustn't be called. So remember what we
  96. +           have pushed and pop only if that is matched by 
  97. +           current_binding_level later. mnl@dtro.e-technik.th-darmstadt.de */
  98. +        local_binding_level = current_binding_level;
  99.         loc_typedecl = start_decl (declarator, declspecs, initialized, NULL_TREE);
  100.   
  101.         pi = (int *) permalloc (sizeof (struct lang_decl_flags));
  102. ***************
  103. *** 7256,7262 ****
  104.         DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi;
  105.         /* This poplevel conflicts with the popclass over in
  106.            grokdeclarator.  See ``This popclass conflicts'' */
  107. !       poplevel (0, 0, 0);
  108.   
  109.   #if 0
  110.         if (TREE_CODE (TREE_TYPE (loc_typedecl)) == ENUMERAL_TYPE)
  111. --- 7263,7270 ----
  112.         DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi;
  113.         /* This poplevel conflicts with the popclass over in
  114.            grokdeclarator.  See ``This popclass conflicts'' */
  115. !        if (current_binding_level == local_binding_level)
  116. !         poplevel (0, 0, 0);
  117.   
  118.   #if 0
  119.         if (TREE_CODE (TREE_TYPE (loc_typedecl)) == ENUMERAL_TYPE)
  120.  
  121. Bug2:
  122.  
  123. Compiling this
  124. --------------------------------------------------
  125. // -*- c++ -*-
  126.  
  127. class AnyRpcCallback
  128. {
  129. protected:
  130.  
  131. public:
  132.   inline virtual ~AnyRpcCallback () {}
  133.   inline virtual void Do (void* in, void* out) = 0;
  134. };
  135.  
  136. template<class T> class RpcCallback : public AnyRpcCallback
  137. {
  138.   typedef void (T::*Method)(void*, void*);
  139.   typedef void (T::*MethodN)(void*, void**);
  140.   typedef void (T::*Method1)(void*, void*);
  141.   typedef void (T::*Method2)(void*, void*, void*);
  142.  
  143. private:
  144.   T* object;
  145.   void (T::*method)(void*, void*);
  146.  
  147. public:
  148.   inline RpcCallback (T* o, void* m)
  149.     { object = o; method = m; }
  150.   inline void Do (void* in, void* out)
  151.     { (object->*method)(in, out); }
  152. };
  153.  
  154. class Test
  155. {
  156. public:
  157.   void m (void*, void*);
  158. };
  159.  
  160. main ()
  161. {
  162.   Test o;
  163.   AnyRpcCallback* cb = new RpcCallback<Test> (&o, &Test::m);
  164. }
  165. --------------------------------------------------
  166. results in cc1plus looping infinitely.
  167.  
  168. The problem is that the "chain" field of the tree-nodes used by gcc
  169. for its internal representation is used for various purposes, and in
  170. the case of this template-local typedef, someone lost track of its usage.
  171.  
  172. After parsing, the TYPE_DECL-node created for the typedef is appended
  173. to the scope via "pushlevel". Types in the current scope are linked
  174. using the "chain" field. At the same time, however, all components of
  175. the template are linked together during parsing using the same "chain"
  176. field. Parsing the second typedef, "pushlevel" makes the first typedef
  177. a successor of the second typedef and the subsequent catenation of
  178. components makes the second typedef a successor of the first typedef
  179. thus creating a loop.
  180.  
  181. The resulting list of all components is used in routine
  182. "finish_struct".
  183.  
  184. I think the most proper approach would be to use TREE_LIST nodes in
  185. the list of components as indirect references to the typedef-nodes.
  186. This is easy to achieve, it is, however, very hard to modify
  187. finish_struct in a way that it handles these indirection properly.
  188. Actually, I gave up when I tried to understand & modify the routine
  189. that removes the duplicate declarations from the list of components.
  190.  
  191. There are two easier approaches: (1) Don't include typedefs in the
  192. list of components, (2) use copies of the typedef-node which have an
  193. unused chain field. The first approach assumes that finish_struct
  194. doesn't do anything with typedefs, so it wouldn't be important if they
  195. are missing from the list of components. If this is the case, however,
  196. it can't hurt to use copies of the typedef-nodes (copies of the
  197. originals that are linked in the scope-list), so the second approach
  198. is safer. It can only fail if finish_struct modifies the typedef-nodes
  199. and this modification is significant for the typedef-nodes in the
  200. scope-list (which are, of course, not modified. Only the copies are).
  201.  
  202. So I think the patch is pretty safe. It fixes the problem and doesn't
  203. seem to introduce new ones. I'm aware that typedefs that are local to
  204. templates stretch language features to the limits, but it makes my
  205. C++ interface to RPCs real nice.
  206.  
  207. *** cp-parse.y.orig    Sat Jan  2 15:17:13 1993
  208. --- cp-parse.y    Sat Jan  2 15:18:13 1993
  209. ***************
  210. *** 2335,2341 ****
  211.                 if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
  212.               $$ = grok_enum_decls (t, $2);
  213.                 else
  214. !             $$ = $2;
  215.               }
  216.             end_exception_decls ();
  217.           }
  218. --- 2335,2357 ----
  219.                 if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
  220.               $$ = grok_enum_decls (t, $2);
  221.                 else
  222. !             {
  223. !                /* if a component is a typedef, it is inserted
  224. !                   in the list of nodes that make up the valid
  225. !                   types in the scope. Thus its chain field is
  226. !                   used and can't be used a second time for linking
  227. !                   the components of the struct. So, we make a copy
  228. !                   here. This apparently works. The proper thing
  229. !                   to do, however, would be to use a TREE_LIST
  230. !                   node to reference the typedef. I tried to rewrite
  231. !                   finish_struct accordingly (i.e., ``dereference''
  232. !                   components TREE_LIST before use, but I gave up.
  233. !                   mnl@dtro.e-technik.th-darmstadt.de */
  234. !                if (TREE_CODE ($2) == TYPE_DECL)
  235. !                  $$ = copy_node ($2);
  236. !                else
  237. !                 $$ = $2;
  238. !             }
  239.               }
  240.             end_exception_decls ();
  241.           }
  242.  
  243. Michael
  244.  
  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.