Re: [PATCH, RFC] plugin to warn about surplus includes

2010-05-19 Thread Tom Tromey
 Bernhard == Bernhard Reutner-Fischer rep.dot@gmail.com writes:

Bernhard - should handle structs.

There are some other difficult cases.

First, don't let this discourage you :-).  I think this would be a
useful feature.

I think in general you cannot actually ever tell if a header is unused
or not.  Maybe it will only be used with some set of -D options, or when
some configure option is passed in.  So I think users of a plugin like
this will always have to live with some false reporting.

A header can #define things that are used by other headers.  You would
need to modify libcpp to detect this situation.

Suppose a system header which is used includes a header which is not
used.  In this case, I think a warning about the inner header should be
suppressed -- users generally can't do anything about this.  (There are
other worse cases like this.  You might have a system header that seems
directly unused, but it is the documented way to access some set of
declarations.  E.g., stdio.h might actually just be a bunch of
#includes.)

Tom


[PATCH, RFC] plugin to warn about surplus includes

2010-05-18 Thread Bernhard Reutner-Fischer
Hi,

A couple of days ago i was asking:
does any frontend support some sort of noting that a user-header was
included but no decl of it was ever referenced (i.e. superfluous
#include) ?

I could not find an appropriate tool to diagnose them, so i was thinking
about a gcc plugin to do that.

Would some plugin like the attached be suitable to put into svn if
cleaned up a bit?
If so, where would they live?

Observations while thinking about all this:
- libcpp does not record LC_PSEUDO_ENTER (or something like that),
  so pristine libcpp cannot detect duplicate includes, like iostream
  in attached sample input.cc
- should figure out how to print a help-text for the plugin
  Hints?
- should handle structs.

Thanks in advance for hints on the help-text printing or comments about
the overall idea of such a facility.
/* Dump superfluous, missing or duplicate includes.
 *
 * Copyright (C) 2010 Bernhard Reutner-Fischer
*/
/*
This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
http://www.gnu.org/licenses/.  */

#include config.h
#include system.h
#include gcc-plugin.h
#include coretypes.h
#include tree.h
#include tree-iterator.h
#include tree-pass.h
#include intl.h
#include line-map.h
#include langhooks.h
#include target.h
#include toplev.h /* warning_at */

//#define info warning
#define info(...) /**/

typedef struct include_t {
struct include_t *next;
const char *filename;
source_location location;
} include_t;
static include_t *incs = NULL, *referenced = NULL;

static bool warn_missing;
static bool warn_surplus;

/* Add filename to the end of the include list.  */
static void __attribute__ ((__nonnull__ (2)))
add_include (include_t **head, const char *filename, const source_location loc,
const bool mainfile)
{
  include_t *tail, *elt;

  if (filename == NULL)
gcc_unreachable ();
  tail = *head;
  while (1)
{
  if (tail  strcmp (tail-filename, filename) == 0)
	{
	  const bool old_warn_system_headers = warn_system_headers;

	  warn_system_headers = 1; /* to please warning_at */
	  if (tail-location != loc  mainfile  warn_surplus)
	warning_at (loc, 0, Duplicate include %s, filename);
	  warn_system_headers = old_warn_system_headers;
	  return; /* don't enter duplicate */
	}
  if (tail  tail-next)
	tail = tail-next;
  else
	break;
}
  info (0, ADDING %s, filename);
  elt = XNEW (include_t);
  elt-filename = filename;
  elt-location = loc;
  elt-next = NULL;
  if (tail)
tail-next = elt;
  else
*head = elt;
}

/* Remove filename from the include list.  */
static void __attribute__ ((__nonnull__ (2)))
remove_include (include_t **head, const char *filename)
{
  bool seen;

  if (filename == NULL)
gcc_unreachable ();
  seen = false;
  while (*head)
{
  if (strcmp ((*head)-filename, filename) == 0)
	{
	  include_t *delete = *head;

	  info (0, REMOVE %s, filename);
	  *head = (*head)-next;
	  XDELETE (delete);
	  seen = true;
	  break;
	}
  head = (*head)-next;
}
  if (!seen  warn_missing)
warning (0, Missing include %s, filename);
}

/* Callback function to invoke after GCC finishes parsing a struct.  */

void
handle_struct (void *event_data, void *user_data)
{
  tree type = (tree) event_data;
  if (type == error_mark_node)
	  return;
  warning (0, G_(Process struct %s),
   IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type;
}

static void
fn_add_includes (tree fndecl, const bool mainfile)
{
  tree decl, type;
  const struct line_map *map;

  map = linemap_lookup (line_table, DECL_SOURCE_LOCATION (fndecl));
  if (!MAIN_FILE_P (map))
{
  source_location loc = DECL_SOURCE_LOCATION (fndecl);
  info (0,fn %s: %s, lang_hooks.decl_printable_name (fndecl, 3), LOCATION_FILE (DECL_SOURCE_LOCATION (fndecl)));
  add_include (referenced, LOCATION_FILE (loc), loc, mainfile);
}
  for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
{
  map = linemap_lookup (line_table, DECL_SOURCE_LOCATION (decl));
  if (!MAIN_FILE_P (map))
	{
	  source_location loc = DECL_SOURCE_LOCATION (decl);
	  info (0,fn arg %s: %s, lang_hooks.decl_printable_name (decl, 3), LOCATION_FILE (DECL_SOURCE_LOCATION (decl)));
	  add_include (referenced,
	  LOCATION_FILE (loc),
	  loc,
	  false);
	}
}
}

static void debug_location (location_t l)
{
  fprintf (stderr, LOCATION_FILE=%s\n, LOCATION_FILE (l));
}

static void
operands_add_includes (tree decl, location_t decl_loc, const bool mainfile)
{
  

Re: [PATCH, RFC] plugin to warn about surplus includes

2010-05-18 Thread Steven Bosscher
On 5/18/10, Bernhard Reutner-Fischer rep.dot@gmail.com wrote:
 Hi,

 A couple of days ago i was asking:
 does any frontend support some sort of noting that a user-header was
 included but no decl of it was ever referenced (i.e. superfluous
 #include) ?

 I could not find an appropriate tool to diagnose them, so i was thinking
 about a gcc plugin to do that.

*bows*

Such a plugin would be very welcome for me at least.

Ciao!
Steven


Re: [PATCH, RFC] plugin to warn about surplus includes

2010-05-18 Thread Joel Sherrill

On 05/18/2010 05:53 PM, Steven Bosscher wrote:

On 5/18/10, Bernhard Reutner-Fischerrep.dot@gmail.com  wrote:
   

Hi,

A couple of days ago i was asking:
does any frontend support some sort of noting that a user-header was
included but no decl of it was ever referenced (i.e. superfluous
#include) ?

I could not find an appropriate tool to diagnose them, so i was thinking
about a gcc plugin to do that.
 

*bows*

Such a plugin would be very welcome for me at least.

   

Count me in those who would be interested.

Would there be a way to exclude specific files?  Say something like
config.h that by convention you might want every file to include?

Ciao!
Steven
   


--joel