<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Nov 20, 2008, at 12:27 AM, Chris Lattner wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Nov 18, 2008, at 8:13 AM, Douglas Gregor wrote:</div><blockquote type="cite"><div><blockquote type="cite">+  DiagnosticInfo &operator<<(const SourceRange &R) {<br></blockquote><blockquote type="cite">+    assert((unsigned)DiagObj->NumDiagArgs <<br></blockquote><blockquote type="cite">+           sizeof(DiagObj->DiagRanges)/sizeof(DiagObj- <br></blockquote><blockquote type="cite"><blockquote type="cite">DiagRanges[0]) &&<br></blockquote></blockquote><blockquote type="cite">+           "Too many arguments to diagnostic!");<br></blockquote><blockquote type="cite">+    DiagObj->DiagRanges[DiagObj->NumDiagRanges++] = &R;<br></blockquote><blockquote type="cite">+    return *this;<br></blockquote><blockquote type="cite">+  }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">};<br></blockquote><br>These operator<<'s should be free functions, because we will certainly  <br>have other operator<<'s for DiagnosticInfo elsewhere in the compiler  <br>that must be free functions, e.g.,<br><br><span class="Apple-tab-span" style="white-space:pre">      </span>DiagnosticInfo& operator<<(DiagnosticInfo& DI, QualType Ty); // in  <br>clang/AST/Type.h<br><br>and we don't want non-member and member operator<<'s overloaded  <br>because the available conversions on the first argument differ, and  <br>that causes overloading weirdness.</div></blockquote><br></div><div>Yes, I totally agree.  Okay, I'm to the point where I want to do this.  However, this is not my day.  Please take a look at this patch:</div><div><br></div><div></div><span><operators.patch></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div></div><div><br></div><div>I just move the operators out of the class in a straightforward way.  With this patch, I get build errors like these:</div><div><br></div><div><div><font class="Apple-style-span" face="Courier">Lexer.cpp: In function ‘char DecodeTrigraphChar(const char*, clang::Lexer*)’:</font></div><div><font class="Apple-style-span" face="Courier">Lexer.cpp:352: error: no match for ‘operator<<’ in ‘clang::Lexer::Diag(const char*, unsigned int) const((CP - 2u), 9u) << std::operator+(const std::basic_string<_CharT, _Traits, _Alloc>&, _CharT) [with _Char</font></div><div><font class="Apple-style-span" face="Courier">T = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>](((int)Res))’</font></div><div><font class="Apple-style-span" face="Courier">/Users/sabre/llvm/tools/clang/lib/Lex/../../include/clang/Basic/Diagnostic.h:366: note: candidates are: clang::DiagnosticInfo& clang::operator<<(clang::DiagnosticInfo&, const std::string&)</font></div><div><font class="Apple-style-span" face="Courier">/Users/sabre/llvm/tools/clang/lib/Lex/../../include/clang/Basic/Diagnostic.h:371: note:                 clang::DiagnosticInfo& clang::operator<<(clang::DiagnosticInfo&, const char*)</font></div><div><font class="Apple-style-span" face="Courier">/Users/sabre/llvm/tools/clang/lib/Lex/../../include/clang/Basic/Diagnostic.h:376: note:                 clang::DiagnosticInfo& clang::operator<<(clang::DiagnosticInfo&, int)</font></div><div><font class="Apple-style-span" face="Courier">/Users/sabre/llvm/tools/clang/lib/Lex/../../include/clang/Basic/Diagnostic.h:381: note:                 clang::DiagnosticInfo& clang::operator<<(clang::DiagnosticInfo&, unsigned int)</font></div><div><font class="Apple-style-span" face="Courier">/Users/sabre/llvm/tools/clang/lib/Lex/../../include/clang/Basic/Diagnostic.h:386: note:                 clang::DiagnosticInfo& clang::operator<<(clang::DiagnosticInfo&, const clang::IdentifierInfo*)</font></div><div><font class="Apple-style-span" face="Courier">/Users/sabre/llvm/tools/clang/lib/Lex/../../include/clang/Basic/Diagnostic.h:392: note:                 clang::DiagnosticInfo& clang::operator<<(clang::DiagnosticInfo&, const clang::SourceRange&)</font></div><br></div><div>This is the source line:</div><div><div><div>Lexer *L; char Res;</div></div><div>...</div><div>  L->Diag(CP-2, diag::trigraph_converted) << std::string()+Res;</div></div></div></blockquote><div><br></div><div>The basic problem is that Diag() is returning a temporary, but a non-const (lvalue) reference can't bind to a temporary. I suggest making the first parameter to these operator<<'s either a const DiagnosticInfo& or a DiagnosticInfo. (The former will require a bunch of other member functions to be const, but so what?)</div><br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>This is a good point where we can step back and look at the amazing awfulness of this diagnostic.  It's 'pretty' printing out the expression in question, in a horribly mangled form.  Then it dumps out a candidate list, but manages to not tell me the types that it actually *has* on the LHS/RHS of the <<.  </div></div></blockquote><div><br></div>We should use this kind of thing as a test case for our diagnostics, to see how clear we can make them.<br><br><span class="Apple-tab-span" style="white-space:pre"> </span>- Doug<br></div></body></html>