[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