[cfe-commits] r65570 - in /cfe/trunk: include/clang/Analysis/ include/clang/Basic/ include/clang/Driver/ include/clang/Parse/ lib/Analysis/ lib/Basic/ lib/Driver/ lib/Parse/ lib/Rewrite/ lib/Sema/ test/Parser/ test/SemaTemplate/
Douglas Gregor
dgregor at apple.com
Fri Feb 27 09:50:34 PST 2009
On Feb 26, 2009, at 10:22 PM, Chris Lattner wrote:
>
> On Feb 26, 2009, at 1:00 PM, Douglas Gregor wrote:
>
>> Author: dgregor
>> Date: Thu Feb 26 15:00:50 2009
>> New Revision: 65570
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=65570&view=rev
>> Log:
>> Introduce code modification hints into the diagnostics system. When
>> we
>> know how to recover from an error, we can attach a hint to the
>> diagnostic that states how to modify the code, which can be one of:
>
> Very nice Doug, as you know I'm a big fan of this work!
Thanks for the review!
>
> Please update the diag section of the internals doc to mention this.
Will do.
>
>> +++ cfe/trunk/include/clang/Basic/Diagnostic.h Thu Feb 26 15:00:50
>> 2009
>> @@ -68,6 +68,69 @@
>> };
>> }
>>
>> +/// \brief Annotates a diagnostic with some code that should be
>> +/// inserted, removed, or replaced to fix the problem.
>> +///
>> +/// This kind of hint should be used when we are certain that the
>> +/// 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
>> +/// compilation.
>
> "result *in* successful compilation"?
Yes, thanks.
>
>>
>> +class CodeModificationHint {
>> +public:
>> + /// \brief Tokens that should be removed to correct the error.
>> + SourceRange RemoveRange;
>> +
>> + /// \brief The location at which we should insert code to correct
>> + /// the error.
>> + SourceLocation InsertionLoc;
>> +
>> + /// \brief The actual code to insert at the insertion location,
>> as a
>> + /// string.
>> + std::string CodeToInsert;
>> +
>> + /// \brief Empty code modification hint, indicating that no code
>> + /// modification is known.
>> + CodeModificationHint() : RemoveRange(), InsertionLoc() { }
>> +
>> + /// \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) { }
>> +
>> + /// \brief Create a code modification hint that removes the given
>> + /// source range.
>> + CodeModificationHint(SourceRange RemoveRange)
>> + : RemoveRange(RemoveRange), InsertionLoc(), CodeToInsert() { }
>> +
>> + /// \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) { }
>
> Instead of using ctors with different prototypes to mean magically
> different things, how about using static functions. This gives:
>
> CodeModificationHint::CreateReplacement(...)
> CodeModificationHint::CreateRemoval(...)
> CodeModificationHint::CreateInsertion(...)
>
> instead of different magic protos.
Okay.
>> =============================================
>> --- cfe/trunk/include/clang/Basic/TokenKinds.h (original)
>> +++ cfe/trunk/include/clang/Basic/TokenKinds.h Thu Feb 26 15:00:50
>> 2009
>> @@ -44,6 +44,7 @@
>> };
>>
>> const char *getTokenName(enum TokenKind Kind);
>> +const char *getTokenSpelling(enum TokenKind Kind);
>
> Please add a doxygen comment for these, describing their behavior.
> 'getTokenSpelling' is a misleading name for this method, because
> tok::getTokenSpelling(Tok.getKind()) doesn't return the token's
> spelling.
Sure.
>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/include/clang/Parse/Parser.h (original)
>> +++ cfe/trunk/include/clang/Parse/Parser.h Thu Feb 26 15:00:50 2009
>> @@ -37,6 +37,12 @@
>> /// that this is valid.
>> Token Tok;
>>
>> + // PrevTokLocation - The location of the token we previously
>> + // consumed. This token is used for diagnostics where we
>> expected to
>> + // see a token following another token (e.g., the ';' at the end
>> of
>> + // a statement).
>> + SourceLocation PrevTokLocation;
>
> Have you measured the perf impact of adding this? I expect that
> this is just as expensive as adding one-token lookahead to the
> parser, and is not something that should be done lightly. Notably,
> this impacts *all* reads from the preprocessor, not just the ones
> that could need the info.
It's a copy of a 32-bit integer... but I'll check.
>
>> +++ cfe/trunk/lib/Basic/TokenKinds.cpp Thu Feb 26 15:00:50 2009
>> @@ -27,3 +27,66 @@
>> assert(Kind < tok::NUM_TOKENS);
>> return TokNames[Kind];
>> }
>> +
>> +/// \brief Determines the spelling of simple punctuation tokens like
>> +/// '!' or '%', and returns NULL for literal and annotation tokens.
>
> Please repeat this in the header file, and mention how it handles
> the digraph issue etc. Please explicitly say that if you want to
> preserve spelling in the digraph case that spelling should be used,
> not this method.
Done.
>
>> +++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Feb 26 15:00:50 2009
>> @@ -365,10 +365,19 @@
>>
>> if (!LHS.isInvalid()) {
>> // Combine the LHS and RHS into the LHS (e.g. build AST).
>> - if (TernaryMiddle.isInvalid())
>> + if (TernaryMiddle.isInvalid()) {
>> + // If we're using '>>' as an operator within a template
>> + // argument list (in C++98), suggest the addition of
>> + // parentheses so that the code remains well-formed in C+
>> +0x.
>
> It seems somewhat strange to me to handle this diag here instead of
> sema. Are you sure it wouldn't be more elegant in sema?
Yes, because it's a parsing issue, not a semantic issue. The '>>'
token is treated differently in a template argument list in C++98 vs. C
++0x, and the parser encodes this behavior in getBinOpPrecedence.
However, we don't have the information to diagnose this language
inconsistency until we know that we've parsed the '>>' as an operator
and have both operands of the expression.
>
>> +++ cfe/trunk/lib/Parse/Parser.cpp Thu Feb 26 15:00:50 2009
>> @@ -68,6 +68,28 @@
>> return Diag(Tok.getLocation(), DiagID);
>> }
>>
>> +/// \brief Emits a diagnostic suggesting parentheses surrounding a
>> +/// given range.
>> +///
>> +/// \param Loc The location where we'll emit the diagnostic.
>> +/// \param Loc The kind of diagnostic to emit.
>> +/// \param ParenRange Source range enclosing code that should be
>> parenthesized.
>> +void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK,
>> + SourceRange ParenRange) {
>> + if (!ParenRange.getEnd().isFileID()) {
>> + // 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),
>> ")");
>
> Would it make sense to add a PP.getLocForEndOfToken(SLoc) method or
> something like that?
Yes, it would. Done!
- Doug
More information about the cfe-commits
mailing list