tree.c (decl_function_context): Handle virtual functions.
[gcc.git] / gcc / tree.c
index 82b00e7d59aff49f4ee9d0e3030ae7910ee2f5ac..78ea4cf976a7a9d3d5cedafca27adf9ab6a98a46 100644 (file)
@@ -1191,9 +1191,7 @@ copy_node (node)
     t = (tree) obstack_alloc (current_obstack, length);
   memcpy (t, node, length);
 
-  /* EXPR_WITH_FILE_LOCATION must keep filename info stored in TREE_CHAIN */
-  if (TREE_CODE (node) != EXPR_WITH_FILE_LOCATION)
-    TREE_CHAIN (t) = 0;
+  TREE_CHAIN (t) = 0;
   TREE_ASM_WRITTEN (t) = 0;
 
   if (TREE_CODE_CLASS (code) == 'd')
@@ -2469,6 +2467,10 @@ unsave_expr_now_r (expr)
 {
   enum tree_code code;
 
+  /* There's nothing to do for NULL_TREE.  */
+  if (!expr)
+    return;
+
   unsave_expr_1 (expr);
 
   code = TREE_CODE (expr);
@@ -4800,6 +4802,15 @@ decl_function_context (decl)
 
   if (TREE_CODE (decl) == SAVE_EXPR)
     context = SAVE_EXPR_CONTEXT (decl);
+  /* C++ virtual functions use DECL_CONTEXT for the class of the vtable
+     where we look up the function at runtime.  Such functions always take
+     a first argument of type 'pointer to real context'.
+
+     C++ should really be fixed to use DECL_CONTEXT for the real context,
+     and use something else for the "virtual context".  */
+  else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VINDEX (decl))
+    context = TYPE_MAIN_VARIANT
+      (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
   else
     context = DECL_CONTEXT (decl);