clang API Documentation

Diagnostics.h
Go to the documentation of this file.
00001 //===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 ///
00010 /// \file
00011 /// \brief Diagnostics class to manage error messages.
00012 ///
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
00016 #define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
00017 
00018 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
00019 #include "clang/Basic/LLVM.h"
00020 #include "llvm/ADT/ArrayRef.h"
00021 #include "llvm/ADT/StringRef.h"
00022 #include "llvm/ADT/Twine.h"
00023 #include "llvm/Support/raw_ostream.h"
00024 #include <string>
00025 #include <vector>
00026 
00027 namespace clang {
00028 namespace ast_matchers {
00029 namespace dynamic {
00030 
00031 struct SourceLocation {
00032   SourceLocation() : Line(), Column() {}
00033   unsigned Line;
00034   unsigned Column;
00035 };
00036 
00037 struct SourceRange {
00038   SourceLocation Start;
00039   SourceLocation End;
00040 };
00041 
00042 /// \brief A VariantValue instance annotated with its parser context.
00043 struct ParserValue {
00044   ParserValue() : Text(), Range(), Value() {}
00045   StringRef Text;
00046   SourceRange Range;
00047   VariantValue Value;
00048 };
00049 
00050 /// \brief Helper class to manage error messages.
00051 class Diagnostics {
00052 public:
00053   /// \brief Parser context types.
00054   enum ContextType {
00055     CT_MatcherArg = 0,
00056     CT_MatcherConstruct = 1
00057   };
00058 
00059   /// \brief All errors from the system.
00060   enum ErrorType {
00061     ET_None = 0,
00062 
00063     ET_RegistryMatcherNotFound = 1,
00064     ET_RegistryWrongArgCount = 2,
00065     ET_RegistryWrongArgType = 3,
00066     ET_RegistryNotBindable = 4,
00067     ET_RegistryAmbiguousOverload = 5,
00068     ET_RegistryValueNotFound = 6,
00069 
00070     ET_ParserStringError = 100,
00071     ET_ParserNoOpenParen = 101,
00072     ET_ParserNoCloseParen = 102,
00073     ET_ParserNoComma = 103,
00074     ET_ParserNoCode = 104,
00075     ET_ParserNotAMatcher = 105,
00076     ET_ParserInvalidToken = 106,
00077     ET_ParserMalformedBindExpr = 107,
00078     ET_ParserTrailingCode = 108,
00079     ET_ParserUnsignedError = 109,
00080     ET_ParserOverloadedType = 110
00081   };
00082 
00083   /// \brief Helper stream class.
00084   class ArgStream {
00085   public:
00086     ArgStream(std::vector<std::string> *Out) : Out(Out) {}
00087     template <class T> ArgStream &operator<<(const T &Arg) {
00088       return operator<<(Twine(Arg));
00089     }
00090     ArgStream &operator<<(const Twine &Arg);
00091 
00092   private:
00093     std::vector<std::string> *Out;
00094   };
00095 
00096   /// \brief Class defining a parser context.
00097   ///
00098   /// Used by the parser to specify (possibly recursive) contexts where the
00099   /// parsing/construction can fail. Any error triggered within a context will
00100   /// keep information about the context chain.
00101   /// This class should be used as a RAII instance in the stack.
00102   struct Context {
00103   public:
00104     /// \brief About to call the constructor for a matcher.
00105     enum ConstructMatcherEnum { ConstructMatcher };
00106     Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
00107             const SourceRange &MatcherRange);
00108     /// \brief About to recurse into parsing one argument for a matcher.
00109     enum MatcherArgEnum { MatcherArg };
00110     Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
00111             const SourceRange &MatcherRange, unsigned ArgNumber);
00112     ~Context();
00113 
00114   private:
00115     Diagnostics *const Error;
00116   };
00117 
00118   /// \brief Context for overloaded matcher construction.
00119   ///
00120   /// This context will take care of merging all errors that happen within it
00121   /// as "candidate" overloads for the same matcher.
00122   struct OverloadContext {
00123   public:
00124    OverloadContext(Diagnostics* Error);
00125    ~OverloadContext();
00126 
00127    /// \brief Revert all errors that happened within this context.
00128    void revertErrors();
00129 
00130   private:
00131     Diagnostics *const Error;
00132     unsigned BeginIndex;
00133   };
00134 
00135   /// \brief Add an error to the diagnostics.
00136   ///
00137   /// All the context information will be kept on the error message.
00138   /// \return a helper class to allow the caller to pass the arguments for the
00139   /// error message, using the << operator.
00140   ArgStream addError(const SourceRange &Range, ErrorType Error);
00141 
00142   /// \brief Information stored for one frame of the context.
00143   struct ContextFrame {
00144     ContextType Type;
00145     SourceRange Range;
00146     std::vector<std::string> Args;
00147   };
00148 
00149   /// \brief Information stored for each error found.
00150   struct ErrorContent {
00151     std::vector<ContextFrame> ContextStack;
00152     struct Message {
00153       SourceRange Range;
00154       ErrorType Type;
00155       std::vector<std::string> Args;
00156     };
00157     std::vector<Message> Messages;
00158   };
00159   ArrayRef<ErrorContent> errors() const { return Errors; }
00160 
00161   /// \brief Returns a simple string representation of each error.
00162   ///
00163   /// Each error only shows the error message without any context.
00164   void printToStream(llvm::raw_ostream &OS) const;
00165   std::string toString() const;
00166 
00167   /// \brief Returns the full string representation of each error.
00168   ///
00169   /// Each error message contains the full context.
00170   void printToStreamFull(llvm::raw_ostream &OS) const;
00171   std::string toStringFull() const;
00172 
00173 private:
00174   /// \brief Helper function used by the constructors of ContextFrame.
00175   ArgStream pushContextFrame(ContextType Type, SourceRange Range);
00176 
00177   std::vector<ContextFrame> ContextStack;
00178   std::vector<ErrorContent> Errors;
00179 };
00180 
00181 }  // namespace dynamic
00182 }  // namespace ast_matchers
00183 }  // namespace clang
00184 
00185 #endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H