1259701Sdim//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim/// 10259701Sdim/// \file 11259701Sdim/// \brief Diagnostics class to manage error messages. 12259701Sdim/// 13259701Sdim//===----------------------------------------------------------------------===// 14259701Sdim 15259701Sdim#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H 16259701Sdim#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H 17259701Sdim 18259701Sdim#include <string> 19259701Sdim#include <vector> 20259701Sdim 21259701Sdim#include "clang/ASTMatchers/Dynamic/VariantValue.h" 22259701Sdim#include "clang/Basic/LLVM.h" 23259701Sdim#include "llvm/ADT/ArrayRef.h" 24259701Sdim#include "llvm/ADT/StringRef.h" 25259701Sdim#include "llvm/ADT/Twine.h" 26259701Sdim#include "llvm/Support/raw_ostream.h" 27259701Sdim 28259701Sdimnamespace clang { 29259701Sdimnamespace ast_matchers { 30259701Sdimnamespace dynamic { 31259701Sdim 32259701Sdimstruct SourceLocation { 33259701Sdim SourceLocation() : Line(), Column() {} 34259701Sdim unsigned Line; 35259701Sdim unsigned Column; 36259701Sdim}; 37259701Sdim 38259701Sdimstruct SourceRange { 39259701Sdim SourceLocation Start; 40259701Sdim SourceLocation End; 41259701Sdim}; 42259701Sdim 43259701Sdim/// \brief A VariantValue instance annotated with its parser context. 44259701Sdimstruct ParserValue { 45259701Sdim ParserValue() : Text(), Range(), Value() {} 46259701Sdim StringRef Text; 47259701Sdim SourceRange Range; 48259701Sdim VariantValue Value; 49259701Sdim}; 50259701Sdim 51259701Sdim/// \brief Helper class to manage error messages. 52259701Sdimclass Diagnostics { 53259701Sdimpublic: 54259701Sdim /// \brief Parser context types. 55259701Sdim enum ContextType { 56259701Sdim CT_MatcherArg = 0, 57259701Sdim CT_MatcherConstruct = 1 58259701Sdim }; 59259701Sdim 60259701Sdim /// \brief All errors from the system. 61259701Sdim enum ErrorType { 62259701Sdim ET_None = 0, 63259701Sdim 64259701Sdim ET_RegistryNotFound = 1, 65259701Sdim ET_RegistryWrongArgCount = 2, 66259701Sdim ET_RegistryWrongArgType = 3, 67259701Sdim ET_RegistryNotBindable = 4, 68259701Sdim ET_RegistryAmbiguousOverload = 5, 69259701Sdim 70259701Sdim ET_ParserStringError = 100, 71259701Sdim ET_ParserNoOpenParen = 101, 72259701Sdim ET_ParserNoCloseParen = 102, 73259701Sdim ET_ParserNoComma = 103, 74259701Sdim ET_ParserNoCode = 104, 75259701Sdim ET_ParserNotAMatcher = 105, 76259701Sdim ET_ParserInvalidToken = 106, 77259701Sdim ET_ParserMalformedBindExpr = 107, 78259701Sdim ET_ParserTrailingCode = 108, 79259701Sdim ET_ParserUnsignedError = 109, 80259701Sdim ET_ParserOverloadedType = 110 81259701Sdim }; 82259701Sdim 83259701Sdim /// \brief Helper stream class. 84259701Sdim class ArgStream { 85259701Sdim public: 86259701Sdim ArgStream(std::vector<std::string> *Out) : Out(Out) {} 87259701Sdim template <class T> ArgStream &operator<<(const T &Arg) { 88259701Sdim return operator<<(Twine(Arg)); 89259701Sdim } 90259701Sdim ArgStream &operator<<(const Twine &Arg); 91259701Sdim 92259701Sdim private: 93259701Sdim std::vector<std::string> *Out; 94259701Sdim }; 95259701Sdim 96259701Sdim /// \brief Class defining a parser context. 97259701Sdim /// 98259701Sdim /// Used by the parser to specify (possibly recursive) contexts where the 99259701Sdim /// parsing/construction can fail. Any error triggered within a context will 100259701Sdim /// keep information about the context chain. 101259701Sdim /// This class should be used as a RAII instance in the stack. 102259701Sdim struct Context { 103259701Sdim public: 104259701Sdim /// \brief About to call the constructor for a matcher. 105259701Sdim enum ConstructMatcherEnum { ConstructMatcher }; 106259701Sdim Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName, 107259701Sdim const SourceRange &MatcherRange); 108259701Sdim /// \brief About to recurse into parsing one argument for a matcher. 109259701Sdim enum MatcherArgEnum { MatcherArg }; 110259701Sdim Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName, 111259701Sdim const SourceRange &MatcherRange, unsigned ArgNumber); 112259701Sdim ~Context(); 113259701Sdim 114259701Sdim private: 115259701Sdim Diagnostics *const Error; 116259701Sdim }; 117259701Sdim 118259701Sdim /// \brief Context for overloaded matcher construction. 119259701Sdim /// 120259701Sdim /// This context will take care of merging all errors that happen within it 121259701Sdim /// as "candidate" overloads for the same matcher. 122259701Sdim struct OverloadContext { 123259701Sdim public: 124259701Sdim OverloadContext(Diagnostics* Error); 125259701Sdim ~OverloadContext(); 126259701Sdim 127259701Sdim /// \brief Revert all errors that happened within this context. 128259701Sdim void revertErrors(); 129259701Sdim 130259701Sdim private: 131259701Sdim Diagnostics *const Error; 132259701Sdim unsigned BeginIndex; 133259701Sdim }; 134259701Sdim 135259701Sdim /// \brief Add an error to the diagnostics. 136259701Sdim /// 137259701Sdim /// All the context information will be kept on the error message. 138259701Sdim /// \return a helper class to allow the caller to pass the arguments for the 139259701Sdim /// error message, using the << operator. 140259701Sdim ArgStream addError(const SourceRange &Range, ErrorType Error); 141259701Sdim 142259701Sdim /// \brief Information stored for one frame of the context. 143259701Sdim struct ContextFrame { 144259701Sdim ContextType Type; 145259701Sdim SourceRange Range; 146259701Sdim std::vector<std::string> Args; 147259701Sdim }; 148259701Sdim 149259701Sdim /// \brief Information stored for each error found. 150259701Sdim struct ErrorContent { 151259701Sdim std::vector<ContextFrame> ContextStack; 152259701Sdim struct Message { 153259701Sdim SourceRange Range; 154259701Sdim ErrorType Type; 155259701Sdim std::vector<std::string> Args; 156259701Sdim }; 157259701Sdim std::vector<Message> Messages; 158259701Sdim }; 159259701Sdim ArrayRef<ErrorContent> errors() const { return Errors; } 160259701Sdim 161259701Sdim /// \brief Returns a simple string representation of each error. 162259701Sdim /// 163259701Sdim /// Each error only shows the error message without any context. 164259701Sdim void printToStream(llvm::raw_ostream &OS) const; 165259701Sdim std::string toString() const; 166259701Sdim 167259701Sdim /// \brief Returns the full string representation of each error. 168259701Sdim /// 169259701Sdim /// Each error message contains the full context. 170259701Sdim void printToStreamFull(llvm::raw_ostream &OS) const; 171259701Sdim std::string toStringFull() const; 172259701Sdim 173259701Sdimprivate: 174259701Sdim /// \brief Helper function used by the constructors of ContextFrame. 175259701Sdim ArgStream pushContextFrame(ContextType Type, SourceRange Range); 176259701Sdim 177259701Sdim std::vector<ContextFrame> ContextStack; 178259701Sdim std::vector<ErrorContent> Errors; 179259701Sdim}; 180259701Sdim 181259701Sdim} // namespace dynamic 182259701Sdim} // namespace ast_matchers 183259701Sdim} // namespace clang 184259701Sdim 185259701Sdim#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H 186