Esempio n. 1
0
static void
lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p)
{
  symtab_node *prevailing;
  symtab_node *e;
  vec<tree> mismatches = vNULL;
  unsigned i;
  tree decl;
  bool tbaa_p = false;

  /* Nothing to do for a single entry.  */
  prevailing = first;
  if (!prevailing->next_sharing_asm_name)
    return;

  /* Try to merge each entry with the prevailing one.  */
  symtab_node *last_prevailing = prevailing, *next;
  for (e = prevailing->next_sharing_asm_name; e; e = next)
    {
      next = e->next_sharing_asm_name;

      /* Skip non-LTO symbols and symbols whose declaration we already
	 visited.  */
      if (lto_symtab_prevailing_decl (e->decl) != e->decl
	  || !lto_symtab_symbol_p (e)
          || e->decl == prevailing->decl)
	continue;

      if (!lto_symtab_merge (prevailing, e)
	  && !diagnosed_p
	  && !DECL_ARTIFICIAL (e->decl))
	mismatches.safe_push (e->decl);

      symtab_node *this_prevailing;
      for (this_prevailing = prevailing; ;
	   this_prevailing = this_prevailing->next_sharing_asm_name)
	{
	  if (this_prevailing->decl != e->decl
	      && lto_symtab_merge_p (this_prevailing->decl, e->decl))
	    break;
	  if (this_prevailing == last_prevailing)
	    {
	      this_prevailing = NULL;
	      break;
	    }
	}

      if (this_prevailing)
	lto_symtab_prevail_decl (this_prevailing->decl, e->decl);
      /* Maintain LRU list: relink the new prevaililng symbol
	 just after previaling node in the chain and update last_prevailing.
	 Since the number of possible declarations of a given symbol is
	 small, this should be faster than building a hash.  */
      else if (e == prevailing->next_sharing_asm_name)
	last_prevailing = e;
      else
	{
	  if (e->next_sharing_asm_name)
	    e->next_sharing_asm_name->previous_sharing_asm_name
	      = e->previous_sharing_asm_name;
	  e->previous_sharing_asm_name->next_sharing_asm_name
	    = e->next_sharing_asm_name;
	  e->previous_sharing_asm_name = prevailing;
	  e->next_sharing_asm_name = prevailing->next_sharing_asm_name;
	  prevailing->next_sharing_asm_name->previous_sharing_asm_name = e;
	  prevailing->next_sharing_asm_name = e;
	  if (last_prevailing == prevailing)
	    last_prevailing = e;
	}
    }
  if (mismatches.is_empty ())
    return;

  /* Diagnose all mismatched re-declarations.  */
  FOR_EACH_VEC_ELT (mismatches, i, decl)
    {
      int level = warn_type_compatibility_p (TREE_TYPE (prevailing->decl),
					     TREE_TYPE (decl),
					     DECL_COMDAT (decl));
      if (level)
	{
	  bool diag = false;
	  if (level & 2)
	    diag = warning_at (DECL_SOURCE_LOCATION (decl),
			       OPT_Wodr,
			       "%qD violates the C++ One Definition Rule ",
			       decl);
	  if (!diag && (level & 1))
	    diag = warning_at (DECL_SOURCE_LOCATION (decl),
			       OPT_Wlto_type_mismatch,
			       "type of %qD does not match original "
			       "declaration", decl);
	  if (diag)
	    {
	      warn_types_mismatch (TREE_TYPE (prevailing->decl),
				   TREE_TYPE (decl),
				   DECL_SOURCE_LOCATION (prevailing->decl),
				   DECL_SOURCE_LOCATION (decl));
	      if ((level & 4)
		  && !TREE_READONLY (prevailing->decl))
		tbaa_p = true;
	    }
	  diagnosed_p |= diag;
	}
      else if ((DECL_USER_ALIGN (prevailing->decl)
	        && DECL_USER_ALIGN (decl))
	       && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
	{
	  diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl),
				     OPT_Wlto_type_mismatch,
				     "alignment of %qD is bigger than "
				     "original declaration", decl);
	}
      else
	diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl),
				   OPT_Wlto_type_mismatch,
				   "size of %qD differ from the size of "
				   "original declaration", decl);
    }
Esempio n. 2
0
static void
lto_symtab_merge_symbols_1 (symtab_node *prevailing)
{
  symtab_node *e;
  symtab_node *next;

  prevailing->decl->decl_with_vis.symtab_node = prevailing;

  /* Replace the cgraph node of each entry with the prevailing one.  */
  for (e = prevailing->next_sharing_asm_name; e;
       e = next)
    {
      next = e->next_sharing_asm_name;

      if (!lto_symtab_symbol_p (e))
	continue;
      cgraph_node *ce = dyn_cast <cgraph_node *> (e);
      symtab_node *to = symtab_node::get (lto_symtab_prevailing_decl (e->decl));

      /* No matter how we are going to deal with resolution, we will ultimately
	 use prevailing definition.  */
      if (ce)
          ipa_merge_profiles (dyn_cast<cgraph_node *> (prevailing),
			      dyn_cast<cgraph_node *> (e));

      /* If we decided to replace the node by TO, do it.  */
      if (e != to)
	{
	  if (ce)
	    lto_cgraph_replace_node (ce, dyn_cast<cgraph_node *> (to));
	  else if (varpool_node *ve = dyn_cast <varpool_node *> (e))
	    lto_varpool_replace_node (ve, dyn_cast<varpool_node *> (to));
	}
      /* Watch out for duplicated symbols for a given declaration.  */
      else if (!e->transparent_alias
	       || !e->definition || e->get_alias_target () != to)
	{
	  /* We got a new declaration we do not want to merge.  In this case
	     get rid of the existing definition and create a transparent
	     alias.  */
	  if (ce)
	    {
	      lto_free_function_in_decl_state_for_node (ce);
	      if (!ce->weakref)
	        ce->release_body ();
	      ce->reset ();
	      symtab->call_cgraph_removal_hooks (ce);
	    }
	  else
	    {
	      DECL_INITIAL (e->decl) = error_mark_node;
	      if (e->lto_file_data)
		{
		  lto_free_function_in_decl_state_for_node (e);
		  e->lto_file_data = NULL;
		}
	      symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e));
	    }
	  e->remove_all_references ();
	  e->analyzed = e->body_removed = false;
	  e->resolve_alias (prevailing, true);
	  gcc_assert (e != prevailing);
	}
    }

  return;
}