[cfe-commits] r65641 - in /cfe/trunk: docs/InternalsManual.html include/clang/Basic/Diagnostic.h include/clang/Basic/TokenKinds.h include/clang/Lex/Preprocessor.h lib/Basic/TokenKinds.cpp lib/Lex/Preprocessor.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Fri Feb 27 09:53:18 PST 2009


Author: dgregor
Date: Fri Feb 27 11:53:17 2009
New Revision: 65641

URL: http://llvm.org/viewvc/llvm-project?rev=65641&view=rev
Log:
Clean up and document code modification hints.

Modified:
    cfe/trunk/docs/InternalsManual.html
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/include/clang/Basic/TokenKinds.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Basic/TokenKinds.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/docs/InternalsManual.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/InternalsManual.html?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/docs/InternalsManual.html (original)
+++ cfe/trunk/docs/InternalsManual.html Fri Feb 27 11:53:17 2009
@@ -386,6 +386,63 @@
 it is rendered.
 </p>
 
+<!-- ==================================================== -->
+<h4 id="code-modification-hints">Code Modification Hints</h4>
+<!-- ==================================================== -->
+
+<p>In some cases, the front end emits diagnostics when it is clear
+that some small change to the source code would fix the problem. For
+example, a missing semicolon at the end of a statement or a use of
+deprecated syntax that is easily rewritten into a more modern form. In
+these cases, the front end should emit the diagnostic and recover
+gracefully.</p>
+
+<p>In these cases, the diagnostic can be annotation with a code
+modification "hint" that describes how to modify the code referenced
+by the diagnostic to fix the problem. For example, it might add the
+missing semicolon at the end of the statement or rewrite the use of a
+deprecated construct into something more palatable. Here is one such
+example C++ front end, where we warn about the right-shift operator
+changing meaning from C++98 to C++0x:</p>
+
+<pre>
+test.cpp:3:7: warning: use of right-shift operator ('>>') in template argument will require parentheses in C++0x
+A<100 >> 2> *a;
+      ^
+  (       )
+</pre>
+
+<p>Here, the code modification hint is suggesting that parentheses be
+added, and showing exactly where those parentheses would be inserted
+into the source code. The code modification hints themselves describe
+what changes to make to the source code in an abstract manner, which
+the text diagnostic printer renders as a line of "insertions" below
+the caret line. <a href="#DiagnosticClient">Other diagnostic
+clients</a> might choose to render the code differently (e.g., as
+markup inline) or even give the user the ability to automatically fix
+the problem.</p>
+
+<p>All code modification hints are described by the
+<code>CodeModificationHint</code> class, instances of which should be
+attached to the diagnostic using the << operator in the same way
+that highlighted source ranges and arguments are passed to the
+diagnostic. Code modification hints can be created with one of three
+constructors:</p>
+
+<dl>
+  <dt><code>CodeModificationHint::CreateInsertion(Loc, Code)</code></dt>
+  <dd>Specifies that the given <code>Code</code> (a string) should be inserted
+  before the source location <code>Loc</code>.</dd>
+
+  <dt><code>CodeModificationHint::CreateRemoval(Range)</code></dt>
+  <dd>Specifies that the code in the given source <code>Range</code>
+  should be removed.</dd>
+
+  <dt><code>CodeModificationHint::CreateReplacement(Range, Code)</code></dt>
+  <dd>Specifies that the code in the given source <code>Range</code>
+  should be removed, and replaced with the given <code>Code</code> string.</dd>
+</dl>
+
 <!-- ============================================================= -->
 <h4><a name="DiagnosticClient">The DiagnosticClient Interface</a></h4>
 <!-- ============================================================= -->

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Fri Feb 27 11:53:17 2009
@@ -75,7 +75,7 @@
 /// introduction, removal, or modification of a particular (small!)
 /// amount of code will correct a compilation error. The compiler
 /// should also provide full recovery from such errors, such that
-/// suppressing the diagnostic output can still result successful
+/// suppressing the diagnostic output can still result in successful
 /// compilation.
 class CodeModificationHint {
 public:
@@ -96,41 +96,34 @@
 
   /// \brief Create a code modification hint that inserts the given
   /// code string at a specific location.
-  CodeModificationHint(SourceLocation InsertionLoc, const std::string &Code)
-    : RemoveRange(), InsertionLoc(InsertionLoc), CodeToInsert(Code) { }
+  static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, 
+                                              const std::string &Code) {
+    CodeModificationHint Hint;
+    Hint.InsertionLoc = InsertionLoc;
+    Hint.CodeToInsert = Code;
+    return Hint;
+  }
 
   /// \brief Create a code modification hint that removes the given
   /// source range.
-  CodeModificationHint(SourceRange RemoveRange)
-    : RemoveRange(RemoveRange), InsertionLoc(), CodeToInsert() { }
+  static CodeModificationHint CreateRemoval(SourceRange RemoveRange) {
+    CodeModificationHint Hint;
+    Hint.RemoveRange = RemoveRange;
+    return Hint;
+  }
 
   /// \brief Create a code modification hint that replaces the given
   /// source range with the given code string.
-  CodeModificationHint(SourceRange RemoveRange, const std::string &Code)
-    : RemoveRange(RemoveRange), InsertionLoc(RemoveRange.getBegin()),
-      CodeToInsert(Code) { }
+  static CodeModificationHint CreateReplacement(SourceRange RemoveRange, 
+                                                const std::string &Code) {
+    CodeModificationHint Hint;
+    Hint.RemoveRange = RemoveRange;
+    Hint.InsertionLoc = RemoveRange.getBegin();
+    Hint.CodeToInsert = Code;
+    return Hint;
+  }
 };
 
-/// \brief Creates a code modification hint that inserts the given
-/// string at a particular location in the source code.
-inline CodeModificationHint 
-CodeInsertionHint(SourceLocation InsertionLoc, const std::string &Code) {
-  return CodeModificationHint(InsertionLoc, Code);
-}
-
-/// \brief Creates a code modification hint that removes the given
-/// source range.
-inline CodeModificationHint CodeRemovalHint(SourceRange RemoveRange) {
-  return CodeModificationHint(RemoveRange);
-}
-
-/// \brief Creates a code modification hint that replaces the given
-/// source range with the given code string.
-inline CodeModificationHint 
-CodeReplacementHint(SourceRange RemoveRange, const std::string &Code) {
-  return CodeModificationHint(RemoveRange, Code);
-}
-
 /// Diagnostic - This concrete class is used by the front-end to report
 /// problems and issues.  It massages the diagnostics (e.g. handling things like
 /// "report warnings as errors" and passes them off to the DiagnosticClient for

Modified: cfe/trunk/include/clang/Basic/TokenKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.h?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.h (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.h Fri Feb 27 11:53:17 2009
@@ -43,8 +43,20 @@
   NUM_OBJC_KEYWORDS
 };
 
+/// \brief Determines the name of a token as used within the front end.
+///
+/// The name of a token will be an internal name (such as "l_square")
+/// and should not be used as part of diagnostic messages.
 const char *getTokenName(enum TokenKind Kind);
-const char *getTokenSpelling(enum TokenKind Kind);
+
+/// \brief Determines the spelling of simple punctuation tokens like
+/// '!' or '%', and returns NULL for literal and annotation tokens.
+///
+/// This routine only retrieves the "simple" spelling of the token,
+/// and will not produce any alternative spellings (e.g., a
+/// digraph). For the actual spelling of a given Token, use
+/// Preprocessor::getSpelling().
+const char *getTokenSimpleSpelling(enum TokenKind Kind);
 
 }  // end namespace tok
 }  // end namespace clang

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri Feb 27 11:53:17 2009
@@ -476,7 +476,7 @@
   /// copy).  The caller is not allowed to modify the returned buffer pointer
   /// if an internal buffer is returned.
   unsigned getSpelling(const Token &Tok, const char *&Buffer) const;
-  
+
   /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant
   /// with length 1, return the character.
   char getSpellingOfSingleCharacterNumericConstant(const Token &Tok) const {
@@ -498,7 +498,19 @@
   /// location provides a location of the instantiation point of the token.
   void CreateString(const char *Buf, unsigned Len,
                     Token &Tok, SourceLocation SourceLoc = SourceLocation());
-  
+
+  /// \brief Computes the source location just past the end of the
+  /// token at this source location.
+  ///
+  /// This routine can be used to produce a source location that
+  /// points just past the end of the token referenced by \p Loc, and
+  /// is generally used when a diagnostic needs to point just after a
+  /// token where it expected something different that it received. If
+  /// the returned source location would not be meaningful (e.g., if
+  /// it points into a macro), this routine returns an invalid
+  /// source location.
+  SourceLocation getLocForEndOfToken(SourceLocation Loc);
+    
   /// DumpToken - Print the token to stderr, used for debugging.
   ///
   void DumpToken(const Token &Tok, bool DumpFlags = false) const;

Modified: cfe/trunk/lib/Basic/TokenKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/TokenKinds.cpp?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/TokenKinds.cpp (original)
+++ cfe/trunk/lib/Basic/TokenKinds.cpp Fri Feb 27 11:53:17 2009
@@ -28,9 +28,7 @@
   return TokNames[Kind];
 }
 
-/// \brief Determines the spelling of simple punctuation tokens like
-/// '!' or '%', and returns NULL for literal and annotation tokens.
-const char *tok::getTokenSpelling(enum TokenKind Kind) {
+const char *tok::getTokenSimpleSpelling(enum TokenKind Kind) {
   switch (Kind) {
   case tok::l_square:            return "[";
   case tok::r_square:            return "]";

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Feb 27 11:53:17 2009
@@ -265,7 +265,6 @@
   return OutBuf-Buffer;
 }
 
-
 /// CreateString - Plop the specified string into a scratch buffer and return a
 /// location for it.  If specified, the source location provides a source
 /// location for the token.
@@ -321,6 +320,25 @@
   return TokStart.getFileLocWithOffset(PhysOffset);
 }
 
+/// \brief Computes the source location just past the end of the
+/// token at this source location.
+///
+/// This routine can be used to produce a source location that
+/// points just past the end of the token referenced by \p Loc, and
+/// is generally used when a diagnostic needs to point just after a
+/// token where it expected something different that it received. If
+/// the returned source location would not be meaningful (e.g., if
+/// it points into a macro), this routine returns an invalid
+/// source location.
+SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc) {
+  if (Loc.isInvalid() || !Loc.isFileID())
+    return SourceLocation();
+
+  unsigned Len = Lexer::MeasureTokenLength(Loc, getSourceManager());
+  return AdvanceToTokenCharacter(Loc, Len);
+}
+
+
 
 //===----------------------------------------------------------------------===//
 // Preprocessor Initialization Methods

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Fri Feb 27 11:53:17 2009
@@ -445,7 +445,8 @@
         ReplaceStr = "> > ";
 
       Diag(Tok.getLocation(), diag::err_two_right_angle_brackets_need_space)
-        << CodeReplacementHint(SourceRange(Tok.getLocation()), ReplaceStr);
+        << CodeModificationHint::CreateReplacement(
+                                 SourceRange(Tok.getLocation()), ReplaceStr);
     }
 
     Tok.setKind(tok::greater);

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri Feb 27 11:53:17 2009
@@ -76,18 +76,17 @@
 /// \param ParenRange Source range enclosing code that should be parenthesized.
 void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK,
                                 SourceRange ParenRange) {
-  if (!ParenRange.getEnd().isFileID()) {
+  SourceLocation EndLoc = PP.getLocForEndOfToken(ParenRange.getEnd());
+  if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
     // We can't display the parentheses, so just dig the
     // warning/error and return.
     Diag(Loc, DK);
     return;
   }
     
-  unsigned Len = Lexer::MeasureTokenLength(ParenRange.getEnd(), 
-                                           PP.getSourceManager());
   Diag(Loc, DK) 
-    << CodeInsertionHint(ParenRange.getBegin(), "(")
-    << CodeInsertionHint(ParenRange.getEnd().getFileLocWithOffset(Len), ")");
+    << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
+    << CodeModificationHint::CreateInsertion(EndLoc, ")");
 }
 
 /// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
@@ -131,14 +130,13 @@
   }
 
   const char *Spelling = 0;
-  if (PrevTokLocation.isValid() && PrevTokLocation.isFileID() &&
-      (Spelling = tok::getTokenSpelling(ExpectedTok))) {
+  SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
+  if (EndLoc.isValid() && 
+      (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
     // Show what code to insert to fix this problem.
-    SourceLocation DiagLoc 
-      = PrevTokLocation.getFileLocWithOffset(strlen(Spelling));
-    Diag(DiagLoc, DiagID) 
+    Diag(EndLoc, DiagID) 
       << Msg
-      << CodeInsertionHint(DiagLoc, Spelling);
+      << CodeModificationHint::CreateInsertion(EndLoc, Spelling);
   } else
     Diag(Tok, DiagID) << Msg;
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=65641&r1=65640&r2=65641&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb 27 11:53:17 2009
@@ -1617,7 +1617,7 @@
   // template<> headers.
   if (TemplateParameterLists.size() == 0)
     Diag(KWLoc, diag::err_template_spec_needs_header)
-      << CodeInsertionHint(KWLoc, "template<> ");
+      << CodeModificationHint::CreateInsertion(KWLoc, "template<> ");
   else {
     TemplateParameterList *TemplateParams 
       = static_cast<TemplateParameterList*>(*TemplateParameterLists.get());





More information about the cfe-commits mailing list