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