[cfe-commits] [Patch] Add highlighting and type eliding when two templates are used in a diagnostics. Also, template tree printing.

Richard Trieu rtrieu at google.com
Mon Dec 12 17:43:39 PST 2011


This patch contains new features to help when two templated types are
within a single diagnostic.

New features:
- Selective highlighting within the type name.  Text will be bolded to show
the difference within types.  For instance, if a pair<bool, int> is used
where a pair<double, int>, then the only bool and double will be bold in
the diagnostic.
- Type eliding.  The common type between two templates leaving only types
that important to the structure or differing types.  In a pair<bool, int>
vs pair<double, int>, the diagnostic will show pair<bool, [...]> vs
pair<double, [...]>.  Multiple elided types are stacked to reduced space.
 Controlled by -f(no-)elide-type
- Tree printing.  This feature formats the template as a tree with one type
per line.  This expanded format gives an easier view of the entire
structure.  Continuing with pair<bool, int> vs pair<double, int>, the
output is:
  pair<
    [bool != double]
    int >
This feature is controlled by -f(no-)diagnostics-show-template-tree and
also works with type eliding.

Currently, this feature is only enabled on candidate function notes.

Examples below.

Given this code:
template <typename T1, typename T2> class Alpha {};
template <typename T1, typename T2> class Bravo {};
template <typename T1, typename T2> class Charlie {};
template <typename T1, typename T2> class Delta {};

void Function1(Alpha<int, void>) {};
void Function2(Alpha<Bravo<Charlie<Delta<void, void>, Delta<double,
Alpha<const int, bool> > >, int>, int>) {};

void foo() {
  Function1(Alpha<int, int>());
  Function2(Alpha<Bravo<Charlie<Delta<void, int>, Delta<double, Alpha<const
int, bool> > >, int>, double>());
}

Seeing the error in the Function1 call is easy, but the Function2 is harder.
Currently, clang gives these diagnostics:

templatediff.cc:10:3: error: no matching function for call to 'Function1'
  Function1(Alpha<int, int>());
  ^~~~~~~~~
templatediff.cc:6:6: note: candidate function not viable: no known
conversion
      from 'Alpha<int, int>' to 'Alpha<int, void>' for 1st argument;
void Function1(Alpha<int, void>) {};
     ^
templatediff.cc:11:3: error: no matching function for call to 'Function2'
  Function2(Alpha<Bravo<Charlie<Delta<void, int>, Delta<double, ...
  ^~~~~~~~~
templatediff.cc:7:6: note: candidate function not viable: no known
conversion
      from 'Alpha<Bravo<Charlie<Delta<void, int>, Delta<double, Alpha<const
int,
      bool> > >, int>, double>' to 'Alpha<Bravo<Charlie<Delta<void, void>,
      Delta<double, Alpha<const int, bool> > >, int>, int>' for 1st
argument;
void Function2(Alpha<Bravo<Charlie<Delta<void, void>, Delta<double, ...
     ^
2 errors generated.

Now, with type eliding:

templatediff.cc:10:3: error: no matching function for call to 'Function1'
  Function1(Alpha<int, int>());
  ^~~~~~~~~
templatediff.cc:6:6: note: candidate function not viable: no known
conversion
      from 'Alpha<[...], int>' to 'Alpha<[...], void>' for 1st argument;
void Function1(Alpha<int, void>) {};
     ^
templatediff.cc:11:3: error: no matching function for call to 'Function2'
  Function2(Alpha<Bravo<Charlie<Delta<void, int>, Delta<double, ...
  ^~~~~~~~~
templatediff.cc:7:6: note: candidate function not viable: no known
conversion
      from 'Alpha<Bravo<Charlie<Delta<[...], int>, [...]>, [...]>, double>'
      to 'Alpha<Bravo<Charlie<Delta<[...], void>, [...]>, [...]>, int>' for
      1st argument;
void Function2(Alpha<Bravo<Charlie<Delta<void, void>, Delta<double, ...
     ^
2 errors generated.

Removal of types in common makes the differing types easier to see.  Also,
they would be bolded if the screen supports it.

Once more, with tree printing and no eliding:

templatediff.cc:10:3: error: no matching function for call to 'Function1'
  Function1(Alpha<int, int>());
  ^~~~~~~~~
templatediff.cc:6:6: note: candidate function not viable: no known
conversion
      for 1st argument;
  Alpha<
    int
    [void != int] >
void Function1(Alpha<int, void>) {};
     ^
templatediff.cc:11:3: error: no matching function for call to 'Function2'
  Function2(Alpha<Bravo<Charlie<Delta<void, int>, Delta<double, ...
  ^~~~~~~~~
templatediff.cc:7:6: note: candidate function not viable: no known
conversion
      for 1st argument;
  Alpha<
    Bravo<
      Charlie<
        Delta<
          void
          [void != int] >
        Delta<
          double
          Alpha<
            const int
            _Bool > > >
      int >
    [int != double] >
void Function2(Alpha<Bravo<Charlie<Delta<void, void>, Delta<double, ...
     ^
2 errors generated.

This takes more lines, but gives a detailed look at the templates.

I have attached a patch and also made it available at
http://codereview.appspot.com/5487054/  Questions and comments welcome.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111212/a8f85622/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: template-diff.patch
Type: text/x-patch
Size: 57422 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111212/a8f85622/attachment.bin>


More information about the cfe-commits mailing list