1f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
2f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//
3f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//                     The LLVM Compiler Infrastructure
4f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//
5f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek// This file is distributed under the University of Illinois Open Source
6f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek// License. See LICENSE.TXT for details.
7f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//
8f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//===----------------------------------------------------------------------===//
9f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek///
10f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek/// \file
11f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek/// \brief Diagnostics class to manage error messages.
12f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek///
13f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek//===----------------------------------------------------------------------===//
14f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
15f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
16f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
17f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
18f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#include "clang/ASTMatchers/Dynamic/VariantValue.h"
19f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#include "clang/Basic/LLVM.h"
20f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#include "llvm/ADT/ArrayRef.h"
21f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#include "llvm/ADT/StringRef.h"
22f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#include "llvm/ADT/Twine.h"
232f5a23103f691b1bf7522494fabeaa8f7bd7122bSamuel Benzaquen#include "llvm/Support/raw_ostream.h"
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <string>
25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <vector>
26f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
27f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimeknamespace clang {
28f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimeknamespace ast_matchers {
29f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimeknamespace dynamic {
30f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
31f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimekstruct SourceLocation {
32f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  SourceLocation() : Line(), Column() {}
33f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  unsigned Line;
34f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  unsigned Column;
35f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek};
36f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
37f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimekstruct SourceRange {
38f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  SourceLocation Start;
39f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  SourceLocation End;
40f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek};
41f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
42f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek/// \brief A VariantValue instance annotated with its parser context.
43f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimekstruct ParserValue {
44f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  ParserValue() : Text(), Range(), Value() {}
45f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  StringRef Text;
46f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  SourceRange Range;
47f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  VariantValue Value;
48f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek};
49f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
50f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek/// \brief Helper class to manage error messages.
51f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimekclass Diagnostics {
528a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquenpublic:
538a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Parser context types.
548a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  enum ContextType {
558a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    CT_MatcherArg = 0,
568a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    CT_MatcherConstruct = 1
578a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  };
588a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
59f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  /// \brief All errors from the system.
60f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  enum ErrorType {
61f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    ET_None = 0,
62f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ET_RegistryMatcherNotFound = 1,
64f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    ET_RegistryWrongArgCount = 2,
65f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    ET_RegistryWrongArgType = 3,
664f37d925927dfdd0c770702ffb22de38fc2007dcSamuel Benzaquen    ET_RegistryNotBindable = 4,
670e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen    ET_RegistryAmbiguousOverload = 5,
686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ET_RegistryValueNotFound = 6,
69f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
70f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    ET_ParserStringError = 100,
718a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserNoOpenParen = 101,
728a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserNoCloseParen = 102,
738a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserNoComma = 103,
748a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserNoCode = 104,
758a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserNotAMatcher = 105,
768a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserInvalidToken = 106,
778a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserMalformedBindExpr = 107,
788a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserTrailingCode = 108,
798a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserUnsignedError = 109,
808a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ET_ParserOverloadedType = 110
81f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  };
82f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
83f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  /// \brief Helper stream class.
848a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  class ArgStream {
858a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  public:
868a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ArgStream(std::vector<std::string> *Out) : Out(Out) {}
87f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    template <class T> ArgStream &operator<<(const T &Arg) {
88f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek      return operator<<(Twine(Arg));
89f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    }
90f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    ArgStream &operator<<(const Twine &Arg);
918a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
928a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  private:
93f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek    std::vector<std::string> *Out;
94f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  };
95f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
968a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Class defining a parser context.
978a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  ///
988a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// Used by the parser to specify (possibly recursive) contexts where the
998a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// parsing/construction can fail. Any error triggered within a context will
1008a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// keep information about the context chain.
1018a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// This class should be used as a RAII instance in the stack.
1028a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  struct Context {
1038a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  public:
1048a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    /// \brief About to call the constructor for a matcher.
1058a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    enum ConstructMatcherEnum { ConstructMatcher };
1068a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
1078a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen            const SourceRange &MatcherRange);
1088a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    /// \brief About to recurse into parsing one argument for a matcher.
1098a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    enum MatcherArgEnum { MatcherArg };
1108a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
1118a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen            const SourceRange &MatcherRange, unsigned ArgNumber);
1128a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ~Context();
1138a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
1148a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  private:
1158a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    Diagnostics *const Error;
1168a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  };
1178a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
1180e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  /// \brief Context for overloaded matcher construction.
1190e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  ///
1200e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  /// This context will take care of merging all errors that happen within it
1210e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  /// as "candidate" overloads for the same matcher.
1220e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  struct OverloadContext {
1230e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  public:
1240e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen   OverloadContext(Diagnostics* Error);
1250e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen   ~OverloadContext();
1260e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen
1270e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen   /// \brief Revert all errors that happened within this context.
1280e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen   void revertErrors();
1290e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen
1300e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  private:
1310e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen    Diagnostics *const Error;
1320e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen    unsigned BeginIndex;
1330e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen  };
1340e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen
1358a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Add an error to the diagnostics.
136f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  ///
1378a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// All the context information will be kept on the error message.
1388a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \return a helper class to allow the caller to pass the arguments for the
139f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  /// error message, using the << operator.
1408a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  ArgStream addError(const SourceRange &Range, ErrorType Error);
1418a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
1428a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Information stored for one frame of the context.
1438a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  struct ContextFrame {
1448a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    ContextType Type;
1458a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    SourceRange Range;
1468a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    std::vector<std::string> Args;
1478a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  };
148f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
1498a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Information stored for each error found.
1508a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  struct ErrorContent {
1518a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen    std::vector<ContextFrame> ContextStack;
1520e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen    struct Message {
1530e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen      SourceRange Range;
1540e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen      ErrorType Type;
1550e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen      std::vector<std::string> Args;
1560e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen    };
1570e1896a753845deee5206b28cdbde1640abb9cacSamuel Benzaquen    std::vector<Message> Messages;
158f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek  };
1598a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  ArrayRef<ErrorContent> errors() const { return Errors; }
160f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
1618a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Returns a simple string representation of each error.
1628a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  ///
1638a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// Each error only shows the error message without any context.
1642f5a23103f691b1bf7522494fabeaa8f7bd7122bSamuel Benzaquen  void printToStream(llvm::raw_ostream &OS) const;
1652f5a23103f691b1bf7522494fabeaa8f7bd7122bSamuel Benzaquen  std::string toString() const;
1668a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
1678a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Returns the full string representation of each error.
1688a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  ///
1698a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// Each error message contains the full context.
1702f5a23103f691b1bf7522494fabeaa8f7bd7122bSamuel Benzaquen  void printToStreamFull(llvm::raw_ostream &OS) const;
1712f5a23103f691b1bf7522494fabeaa8f7bd7122bSamuel Benzaquen  std::string toStringFull() const;
172f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
1738a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquenprivate:
1748a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  /// \brief Helper function used by the constructors of ContextFrame.
1758a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  ArgStream pushContextFrame(ContextType Type, SourceRange Range);
1768a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen
1778a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  std::vector<ContextFrame> ContextStack;
1788a77c20375874c0759a5cd5b4a34e83465d821b2Samuel Benzaquen  std::vector<ErrorContent> Errors;
179f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek};
180f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
181f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek}  // namespace dynamic
182f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek}  // namespace ast_matchers
183f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek}  // namespace clang
184f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek
185f7f295f321fd434e1e542844a71f538a56f2f8fbManuel Klimek#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
186