Clean up and document code modification hints.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65641 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/TokenKinds.cpp b/lib/Basic/TokenKinds.cpp
index 3d47863..4afeaf0 100644
--- a/lib/Basic/TokenKinds.cpp
+++ b/lib/Basic/TokenKinds.cpp
@@ -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 "]";
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index ccb179d..26777d9 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -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
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 0209d7b..2aeb182 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -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);
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 134f477..4398ef8 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -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;
 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 97eb9be..5b2e89e 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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());