1*67e74705SXin Li //===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===// 2*67e74705SXin Li // 3*67e74705SXin Li // The LLVM Compiler Infrastructure 4*67e74705SXin Li // 5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source 6*67e74705SXin Li // License. See LICENSE.TXT for details. 7*67e74705SXin Li // 8*67e74705SXin Li //===----------------------------------------------------------------------===// 9*67e74705SXin Li /// 10*67e74705SXin Li /// \file 11*67e74705SXin Li /// \brief Diagnostics class to manage error messages. 12*67e74705SXin Li /// 13*67e74705SXin Li //===----------------------------------------------------------------------===// 14*67e74705SXin Li 15*67e74705SXin Li #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H 16*67e74705SXin Li #define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H 17*67e74705SXin Li 18*67e74705SXin Li #include "clang/ASTMatchers/Dynamic/VariantValue.h" 19*67e74705SXin Li #include "clang/Basic/LLVM.h" 20*67e74705SXin Li #include "llvm/ADT/ArrayRef.h" 21*67e74705SXin Li #include "llvm/ADT/StringRef.h" 22*67e74705SXin Li #include "llvm/ADT/Twine.h" 23*67e74705SXin Li #include "llvm/Support/raw_ostream.h" 24*67e74705SXin Li #include <string> 25*67e74705SXin Li #include <vector> 26*67e74705SXin Li 27*67e74705SXin Li namespace clang { 28*67e74705SXin Li namespace ast_matchers { 29*67e74705SXin Li namespace dynamic { 30*67e74705SXin Li 31*67e74705SXin Li struct SourceLocation { SourceLocationSourceLocation32*67e74705SXin Li SourceLocation() : Line(), Column() {} 33*67e74705SXin Li unsigned Line; 34*67e74705SXin Li unsigned Column; 35*67e74705SXin Li }; 36*67e74705SXin Li 37*67e74705SXin Li struct SourceRange { 38*67e74705SXin Li SourceLocation Start; 39*67e74705SXin Li SourceLocation End; 40*67e74705SXin Li }; 41*67e74705SXin Li 42*67e74705SXin Li /// \brief A VariantValue instance annotated with its parser context. 43*67e74705SXin Li struct ParserValue { ParserValueParserValue44*67e74705SXin Li ParserValue() : Text(), Range(), Value() {} 45*67e74705SXin Li StringRef Text; 46*67e74705SXin Li SourceRange Range; 47*67e74705SXin Li VariantValue Value; 48*67e74705SXin Li }; 49*67e74705SXin Li 50*67e74705SXin Li /// \brief Helper class to manage error messages. 51*67e74705SXin Li class Diagnostics { 52*67e74705SXin Li public: 53*67e74705SXin Li /// \brief Parser context types. 54*67e74705SXin Li enum ContextType { 55*67e74705SXin Li CT_MatcherArg = 0, 56*67e74705SXin Li CT_MatcherConstruct = 1 57*67e74705SXin Li }; 58*67e74705SXin Li 59*67e74705SXin Li /// \brief All errors from the system. 60*67e74705SXin Li enum ErrorType { 61*67e74705SXin Li ET_None = 0, 62*67e74705SXin Li 63*67e74705SXin Li ET_RegistryMatcherNotFound = 1, 64*67e74705SXin Li ET_RegistryWrongArgCount = 2, 65*67e74705SXin Li ET_RegistryWrongArgType = 3, 66*67e74705SXin Li ET_RegistryNotBindable = 4, 67*67e74705SXin Li ET_RegistryAmbiguousOverload = 5, 68*67e74705SXin Li ET_RegistryValueNotFound = 6, 69*67e74705SXin Li 70*67e74705SXin Li ET_ParserStringError = 100, 71*67e74705SXin Li ET_ParserNoOpenParen = 101, 72*67e74705SXin Li ET_ParserNoCloseParen = 102, 73*67e74705SXin Li ET_ParserNoComma = 103, 74*67e74705SXin Li ET_ParserNoCode = 104, 75*67e74705SXin Li ET_ParserNotAMatcher = 105, 76*67e74705SXin Li ET_ParserInvalidToken = 106, 77*67e74705SXin Li ET_ParserMalformedBindExpr = 107, 78*67e74705SXin Li ET_ParserTrailingCode = 108, 79*67e74705SXin Li ET_ParserUnsignedError = 109, 80*67e74705SXin Li ET_ParserOverloadedType = 110 81*67e74705SXin Li }; 82*67e74705SXin Li 83*67e74705SXin Li /// \brief Helper stream class. 84*67e74705SXin Li class ArgStream { 85*67e74705SXin Li public: ArgStream(std::vector<std::string> * Out)86*67e74705SXin Li ArgStream(std::vector<std::string> *Out) : Out(Out) {} 87*67e74705SXin Li template <class T> ArgStream &operator<<(const T &Arg) { 88*67e74705SXin Li return operator<<(Twine(Arg)); 89*67e74705SXin Li } 90*67e74705SXin Li ArgStream &operator<<(const Twine &Arg); 91*67e74705SXin Li 92*67e74705SXin Li private: 93*67e74705SXin Li std::vector<std::string> *Out; 94*67e74705SXin Li }; 95*67e74705SXin Li 96*67e74705SXin Li /// \brief Class defining a parser context. 97*67e74705SXin Li /// 98*67e74705SXin Li /// Used by the parser to specify (possibly recursive) contexts where the 99*67e74705SXin Li /// parsing/construction can fail. Any error triggered within a context will 100*67e74705SXin Li /// keep information about the context chain. 101*67e74705SXin Li /// This class should be used as a RAII instance in the stack. 102*67e74705SXin Li struct Context { 103*67e74705SXin Li public: 104*67e74705SXin Li /// \brief About to call the constructor for a matcher. 105*67e74705SXin Li enum ConstructMatcherEnum { ConstructMatcher }; 106*67e74705SXin Li Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName, 107*67e74705SXin Li SourceRange MatcherRange); 108*67e74705SXin Li /// \brief About to recurse into parsing one argument for a matcher. 109*67e74705SXin Li enum MatcherArgEnum { MatcherArg }; 110*67e74705SXin Li Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName, 111*67e74705SXin Li SourceRange MatcherRange, unsigned ArgNumber); 112*67e74705SXin Li ~Context(); 113*67e74705SXin Li 114*67e74705SXin Li private: 115*67e74705SXin Li Diagnostics *const Error; 116*67e74705SXin Li }; 117*67e74705SXin Li 118*67e74705SXin Li /// \brief Context for overloaded matcher construction. 119*67e74705SXin Li /// 120*67e74705SXin Li /// This context will take care of merging all errors that happen within it 121*67e74705SXin Li /// as "candidate" overloads for the same matcher. 122*67e74705SXin Li struct OverloadContext { 123*67e74705SXin Li public: 124*67e74705SXin Li OverloadContext(Diagnostics* Error); 125*67e74705SXin Li ~OverloadContext(); 126*67e74705SXin Li 127*67e74705SXin Li /// \brief Revert all errors that happened within this context. 128*67e74705SXin Li void revertErrors(); 129*67e74705SXin Li 130*67e74705SXin Li private: 131*67e74705SXin Li Diagnostics *const Error; 132*67e74705SXin Li unsigned BeginIndex; 133*67e74705SXin Li }; 134*67e74705SXin Li 135*67e74705SXin Li /// \brief Add an error to the diagnostics. 136*67e74705SXin Li /// 137*67e74705SXin Li /// All the context information will be kept on the error message. 138*67e74705SXin Li /// \return a helper class to allow the caller to pass the arguments for the 139*67e74705SXin Li /// error message, using the << operator. 140*67e74705SXin Li ArgStream addError(SourceRange Range, ErrorType Error); 141*67e74705SXin Li 142*67e74705SXin Li /// \brief Information stored for one frame of the context. 143*67e74705SXin Li struct ContextFrame { 144*67e74705SXin Li ContextType Type; 145*67e74705SXin Li SourceRange Range; 146*67e74705SXin Li std::vector<std::string> Args; 147*67e74705SXin Li }; 148*67e74705SXin Li 149*67e74705SXin Li /// \brief Information stored for each error found. 150*67e74705SXin Li struct ErrorContent { 151*67e74705SXin Li std::vector<ContextFrame> ContextStack; 152*67e74705SXin Li struct Message { 153*67e74705SXin Li SourceRange Range; 154*67e74705SXin Li ErrorType Type; 155*67e74705SXin Li std::vector<std::string> Args; 156*67e74705SXin Li }; 157*67e74705SXin Li std::vector<Message> Messages; 158*67e74705SXin Li }; errors()159*67e74705SXin Li ArrayRef<ErrorContent> errors() const { return Errors; } 160*67e74705SXin Li 161*67e74705SXin Li /// \brief Returns a simple string representation of each error. 162*67e74705SXin Li /// 163*67e74705SXin Li /// Each error only shows the error message without any context. 164*67e74705SXin Li void printToStream(llvm::raw_ostream &OS) const; 165*67e74705SXin Li std::string toString() const; 166*67e74705SXin Li 167*67e74705SXin Li /// \brief Returns the full string representation of each error. 168*67e74705SXin Li /// 169*67e74705SXin Li /// Each error message contains the full context. 170*67e74705SXin Li void printToStreamFull(llvm::raw_ostream &OS) const; 171*67e74705SXin Li std::string toStringFull() const; 172*67e74705SXin Li 173*67e74705SXin Li private: 174*67e74705SXin Li /// \brief Helper function used by the constructors of ContextFrame. 175*67e74705SXin Li ArgStream pushContextFrame(ContextType Type, SourceRange Range); 176*67e74705SXin Li 177*67e74705SXin Li std::vector<ContextFrame> ContextStack; 178*67e74705SXin Li std::vector<ErrorContent> Errors; 179*67e74705SXin Li }; 180*67e74705SXin Li 181*67e74705SXin Li } // namespace dynamic 182*67e74705SXin Li } // namespace ast_matchers 183*67e74705SXin Li } // namespace clang 184*67e74705SXin Li 185*67e74705SXin Li #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H 186