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