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