diff options
Diffstat (limited to 'clang/include/clang')
-rw-r--r-- | clang/include/clang/Analysis/PathDiagnostic.h | 18 | ||||
-rw-r--r-- | clang/include/clang/Basic/Diagnostic.h | 107 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.def | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/TokenKinds.h | 1 | ||||
-rw-r--r-- | clang/include/clang/Driver/TextDiagnosticPrinter.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 6 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 29 |
7 files changed, 151 insertions, 17 deletions
diff --git a/clang/include/clang/Analysis/PathDiagnostic.h b/clang/include/clang/Analysis/PathDiagnostic.h index bc68ac59116..cee11c27b59 100644 --- a/clang/include/clang/Analysis/PathDiagnostic.h +++ b/clang/include/clang/Analysis/PathDiagnostic.h @@ -31,6 +31,7 @@ public: private: FullSourceLoc Pos; std::string str; + std::vector<CodeModificationHint> CodeModificationHints; DisplayHint Hint; std::vector<SourceRange> ranges; @@ -56,6 +57,10 @@ public: ranges.push_back(SourceRange(B,E)); } + void addCodeModificationHint(const CodeModificationHint& Hint) { + CodeModificationHints.push_back(Hint); + } + typedef const SourceRange* range_iterator; range_iterator ranges_begin() const { @@ -65,7 +70,18 @@ public: range_iterator ranges_end() const { return ranges_begin() + ranges.size(); } - + + typedef const CodeModificationHint *code_modifications_iterator; + + code_modifications_iterator code_modifications_begin() const { + return CodeModificationHints.empty()? 0 : &CodeModificationHints[0]; + } + + code_modifications_iterator code_modifications_end() const { + return CodeModificationHints.empty()? 0 + : &CodeModificationHints[0] + CodeModificationHints.size(); + } + const SourceManager& getSourceManager() const { return Pos.getManager(); } diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index db62ca95e75..7204abbd2af 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -68,6 +68,69 @@ namespace clang { }; } +/// \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. +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) { } +}; + +/// \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 @@ -272,6 +335,9 @@ private: signed char NumDiagArgs; /// NumRanges - This is the number of ranges in the DiagRanges array. unsigned char NumDiagRanges; + /// \brief The number of code modifications hints in the + /// CodeModificationHints array. + unsigned char NumCodeModificationHints; /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum /// values, with one for each argument. This specifies whether the argument @@ -293,6 +359,12 @@ private: /// only support 10 ranges, could easily be extended if needed. const SourceRange *DiagRanges[10]; + enum { MaxCodeModificationHints = 3 }; + + /// CodeModificationHints - If valid, provides a hint with some code + /// to insert, remove, or modify at a particular position. + CodeModificationHint CodeModificationHints[MaxCodeModificationHints]; + /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. void ProcessDiag(); @@ -315,12 +387,13 @@ private: /// for example. class DiagnosticBuilder { mutable Diagnostic *DiagObj; - mutable unsigned NumArgs, NumRanges; + mutable unsigned NumArgs, NumRanges, NumCodeModificationHints; void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT friend class Diagnostic; explicit DiagnosticBuilder(Diagnostic *diagObj) - : DiagObj(diagObj), NumArgs(0), NumRanges(0) {} + : DiagObj(diagObj), NumArgs(0), NumRanges(0), + NumCodeModificationHints(0) {} public: /// Copy constructor. When copied, this "takes" the diagnostic info from the @@ -339,6 +412,7 @@ public: // the Diagnostic object. DiagObj->NumDiagArgs = NumArgs; DiagObj->NumDiagRanges = NumRanges; + DiagObj->NumCodeModificationHints = NumCodeModificationHints; // Process the diagnostic, sending the accumulated information to the // DiagnosticClient. @@ -373,6 +447,12 @@ public: "Too many arguments to diagnostic!"); DiagObj->DiagRanges[NumRanges++] = &R; } + + void AddCodeModificationHint(const CodeModificationHint &Hint) const { + assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints && + "Too many code modification hints!"); + DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint; + } }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -416,6 +496,12 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, DB.AddSourceRange(R); return DB; } + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const CodeModificationHint &Hint) { + DB.AddCodeModificationHint(Hint); + return DB; +} /// Report - Issue the message to the client. DiagID is a member of the @@ -433,7 +519,7 @@ inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){ //===----------------------------------------------------------------------===// /// DiagnosticInfo - This is a little helper class (which is basically a smart -/// pointer that forward info from Diagnostic) that allows clients ot enquire +/// pointer that forward info from Diagnostic) that allows clients to enquire /// about the currently in-flight diagnostic. class DiagnosticInfo { const Diagnostic *DiagObj; @@ -507,14 +593,25 @@ public: return *DiagObj->DiagRanges[Idx]; } - + unsigned getNumCodeModificationHints() const { + return DiagObj->NumCodeModificationHints; + } + + const CodeModificationHint &getCodeModificationHint(unsigned Idx) const { + return DiagObj->CodeModificationHints[Idx]; + } + + const CodeModificationHint *getCodeModificationHints() const { + return DiagObj->NumCodeModificationHints? + &DiagObj->CodeModificationHints[0] : 0; + } + /// FormatDiagnostic - Format this diagnostic into a string, substituting the /// formal arguments into the %0 slots. The result is appended onto the Str /// array. void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const; }; - /// DiagnosticClient - This is an abstract interface implemented by clients of /// the front-end, which formats and prints fully processed diagnostics. class DiagnosticClient { diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.def b/clang/include/clang/Basic/DiagnosticParseKinds.def index 03868cda497..703d6b875cd 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.def +++ b/clang/include/clang/Basic/DiagnosticParseKinds.def @@ -280,6 +280,9 @@ DIAG(err_less_after_template_name_in_nested_name_spec, ERROR, "expected '<' after 'template %0' in nested name specifier") DIAG(err_two_right_angle_brackets_need_space, ERROR, "a space is required between consecutive right angle brackets (use '> >')") +DIAG(warn_cxx0x_right_shift_in_template_arg, WARNING, + "use of right-shift operator ('>>') in template argument will require " + "parentheses in C++0x") // Language specific pragmas diff --git a/clang/include/clang/Basic/TokenKinds.h b/clang/include/clang/Basic/TokenKinds.h index cfef30b4f5e..6a14244362c 100644 --- a/clang/include/clang/Basic/TokenKinds.h +++ b/clang/include/clang/Basic/TokenKinds.h @@ -44,6 +44,7 @@ enum ObjCKeywordKind { }; const char *getTokenName(enum TokenKind Kind); +const char *getTokenSpelling(enum TokenKind Kind); } // end namespace tok } // end namespace clang diff --git a/clang/include/clang/Driver/TextDiagnosticPrinter.h b/clang/include/clang/Driver/TextDiagnosticPrinter.h index 8d702b4934e..4a332b28a8a 100644 --- a/clang/include/clang/Driver/TextDiagnosticPrinter.h +++ b/clang/include/clang/Driver/TextDiagnosticPrinter.h @@ -48,7 +48,9 @@ public: void EmitCaretDiagnostic(SourceLocation Loc, SourceRange *Ranges, unsigned NumRanges, - SourceManager &SM); + SourceManager &SM, + const CodeModificationHint *Hints = 0, + unsigned NumHints = 0); virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info); diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index ebcd79caaee..a7f2e767b3f 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -551,6 +551,12 @@ public: // Primary Expressions. + /// \brief Retrieve the source range that corresponds to the given + /// expression. + virtual SourceRange getExprRange(ExprTy *E) const { + return SourceRange(); + } + /// ActOnIdentifierExpr - Parse an identifier in expression context. /// 'HasTrailingLParen' indicates whether or not the identifier has a '(' /// token immediately after it. diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 1e3ea317dab..5d5265df358 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -37,6 +37,12 @@ class Parser { /// 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; + unsigned short ParenCount, BracketCount, BraceCount; /// Actions - These are the callbacks we invoke as we parse various constructs @@ -175,9 +181,9 @@ private: assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && !isTokenBrace() && "Should consume special tokens with Consume*Token"); - SourceLocation L = Tok.getLocation(); + PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); - return L; + return PrevTokLocation; } /// ConsumeAnyToken - Dispatch to the right Consume* method based on the @@ -204,9 +210,9 @@ private: ++ParenCount; else if (ParenCount) --ParenCount; // Don't let unbalanced )'s drive the count negative. - SourceLocation L = Tok.getLocation(); + PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); - return L; + return PrevTokLocation; } /// ConsumeBracket - This consume method keeps the bracket count up-to-date. @@ -218,9 +224,9 @@ private: else if (BracketCount) --BracketCount; // Don't let unbalanced ]'s drive the count negative. - SourceLocation L = Tok.getLocation(); + PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); - return L; + return PrevTokLocation; } /// ConsumeBrace - This consume method keeps the brace count up-to-date. @@ -232,9 +238,9 @@ private: else if (BraceCount) --BraceCount; // Don't let unbalanced }'s drive the count negative. - SourceLocation L = Tok.getLocation(); + PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); - return L; + return PrevTokLocation; } /// ConsumeStringToken - Consume the current 'peek token', lexing a new one @@ -244,9 +250,9 @@ private: SourceLocation ConsumeStringToken() { assert(isTokenStringLiteral() && "Should only consume string literals with this method"); - SourceLocation L = Tok.getLocation(); + PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); - return L; + return PrevTokLocation; } /// GetLookAheadToken - This peeks ahead N tokens and returns that token @@ -399,6 +405,9 @@ private: DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID); + void SuggestParentheses(SourceLocation Loc, unsigned DK, + SourceRange ParenRange); + /// SkipUntil - Read tokens until we get to the specified token, then consume /// it (unless DontConsume is true). Because we cannot guarantee that the /// token will ever occur, this skips to the next token, or to some likely |