Consider the following code sample: #define ZERO(c) c.set(0) struct S { int a; int b; }; template <class T> class C { T t; public: void set(int x) { t = x; } }; void foo(C<S> &c) { ZERO(c); } When compiled with clang, the instantiation backtrace shows the point of instantiation within the ZERO macro: #> clang ./tst.cc ./tst.cc:15:23: error: no viable overloaded '=' void set(int x) { t = x; } ~ ^ ~ ./tst.cc:20:3: note: in instantiation of member function 'C<struct S>::set' requested here ZERO(c); ^ ./tst.cc:1:19: note: instantiated from: #define ZERO(c) c.set(0) ^ ./tst.cc:3:8: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'struct S const' for 1st argument struct S ^ 3 diagnostics generated. By contract, gcc ignores the macro completely: #> ./install/bin/gcc -c ./tst.cc ./tst.cc: In member function ‘void C<T>::set(int) [with T = S]’: ./tst.cc:20:3: instantiated from here ./tst.cc:15:21: error: no match for ‘operator=’ in ‘this->C<S>::t = x’ ./tst.cc:3:8: note: candidate is: S& S::operator=(const S&) GCC should include macros in instantiation backtraces like clang does.
Sorry for being naive, Dodji, has this anything to do with your recent work? It's still untriaged.
Yes, it's related. With the infrastructure that is in right now, the results are not super for template instantiate backtraces though: $ cat -n test.cc 1 #define ZERO(c) c.set(0) 2 3 struct S 4 { 5 int a; 6 int b; 7 }; 8 9 template <class T> 10 class C 11 { 12 T t; 13 14 public: 15 void set(int x) { t = x; } 16 }; 17 18 void foo(C<S> &c) 19 { 20 ZERO(c); 21 } 22 23 24 $ When cc1plus -quiet -ftrack-macro-expansion ./test.cc yields: test.cc: In instantiation of ‘void C<T>::set(int) [with T = S]’: test.cc:1:24: required from here test.cc:15:21: erreur: no match for ‘operator=’ in ‘((C<S>*)this)->C<S>::t = x’ test.cc:15:21: note: candidate is: test.cc:3:8: note: S& S::operator=(const S&) test.cc:3:8: note: no known conversion for argument 1 from ‘int’ to ‘const S&’ So it points to the spelling location (1:24) of the token involved in the error message, rather than to the expansion point of the macro. I'd like it to mention both, like it does for the C FE. Beside fixing the various bootstrap breakages I have introduced, I'll need to go through the template instantiation error message mechanics to teach them how to use the new macro token tracking infrastructure, I guess. :-) At least we have the infrastructure now. Thank you for the head-up.
With -ftrack-macro-expansion we get: pr45333.cc: In instantiation of ‘void C<T>::set(int) [with T = S]’: pr45333.cc:1:24: required from here pr45333.cc:15:21: error: no match for ‘operator=’ in ‘((C<S>*)this)->C<S>::t = x’ pr45333.cc:15:21: note: candidate is: pr45333.cc:3:8: note: S& S::operator=(const S&) pr45333.cc:3:8: note: no known conversion for argument 1 from ‘int’ to ‘const S&’ So we can track the origin of the instantation to the macro definition, but then we don't show where the macro is invoked from, which is shown without -ftrack-macro-expansion. I think it should show both, like clang does: pr45333.cc: In instantiation of ‘void C<T>::set(int) [with T = S]’: pr45333.cc:1:19: instantiated from macro ZERO pr45333.cc:20:3: required from here pr45333.cc:15:21: error: no match for ‘operator=’ in ‘((C<S>*)this)->C<S>::t = x’ pr45333.cc:15:21: note: candidate is: pr45333.cc:3:8: note: S& S::operator=(const S&) pr45333.cc:3:8: note: no known conversion for argument 1 from ‘int’ to ‘const S&’ Notice that in my ideal output, I also fixed the location given for the first instantation to point to "set" (1:19) and not to the end of the line (1:24).
> So we can track the origin of the instantation to the macro definition, but > then we don't show where the macro is invoked from, which is shown without > -ftrack-macro-expansion. I think it should show both, like clang does Agreed. > Notice that in my ideal output, I also fixed the location given for the first > instantation to point to "set" (1:19) and not to the end of the line > (1:24). Agreed again. I suspect this is related to our (ab)use of the global input_location instead of relying on the precise location of the tokens we are dealing with. So I guess it'll take some iterations to generally get this right, as you know already.
(In reply to comment #4) > > Agreed again. I suspect this is related to our (ab)use of the global > input_location instead of relying on the precise location of the tokens > we are dealing with. So I guess it'll take some iterations to generally > get this right, as you know already. Indeed. I must say it is superb that the infrastructure is there already, once this is a bit more stable, so many new things are possible. You should put a big item in http://gcc.gnu.org/gcc-4.7/changes.html, and some announcement in "News": "Diagnostics in C++ have been significantly improved for 4.7: (1) The reasons for overload and lookup failure are now detailed described (thanks to the work of Nathan Froyd) (2) GCC is able to track macro expansions to provide more accurate locations in diagnostics (thanks to the work of Dodji Seketeli), and (3) Several hundreds of bugs related to diagnostics have been fixed for 4.7 (thanks to the work of Paolo Carlini and other contributors)."