head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.5
	netbsd-11-0-RC3:1.1.1.5
	netbsd-11-0-RC2:1.1.1.5
	netbsd-11-0-RC1:1.1.1.5
	perseant-exfatfs-base-20250801:1.1.1.5
	netbsd-11:1.1.1.5.0.10
	netbsd-11-base:1.1.1.5
	netbsd-10-1-RELEASE:1.1.1.5
	perseant-exfatfs-base-20240630:1.1.1.5
	perseant-exfatfs:1.1.1.5.0.8
	perseant-exfatfs-base:1.1.1.5
	netbsd-8-3-RELEASE:1.1.1.3
	netbsd-9-4-RELEASE:1.1.1.4
	netbsd-10-0-RELEASE:1.1.1.5
	netbsd-10-0-RC6:1.1.1.5
	netbsd-10-0-RC5:1.1.1.5
	netbsd-10-0-RC4:1.1.1.5
	netbsd-10-0-RC3:1.1.1.5
	netbsd-10-0-RC2:1.1.1.5
	netbsd-10-0-RC1:1.1.1.5
	netbsd-10:1.1.1.5.0.6
	netbsd-10-base:1.1.1.5
	netbsd-9-3-RELEASE:1.1.1.4
	cjep_sun2x:1.1.1.5.0.4
	cjep_sun2x-base:1.1.1.5
	cjep_staticlib_x-base1:1.1.1.5
	netbsd-9-2-RELEASE:1.1.1.4
	cjep_staticlib_x:1.1.1.5.0.2
	cjep_staticlib_x-base:1.1.1.5
	netbsd-9-1-RELEASE:1.1.1.4
	phil-wifi-20200421:1.1.1.5
	phil-wifi-20200411:1.1.1.5
	phil-wifi-20200406:1.1.1.5
	netbsd-8-2-RELEASE:1.1.1.3
	netbsd-9-0-RELEASE:1.1.1.4
	netbsd-9-0-RC2:1.1.1.4
	netbsd-9-0-RC1:1.1.1.4
	netbsd-9:1.1.1.4.0.6
	netbsd-9-base:1.1.1.4
	phil-wifi-20190609:1.1.1.4
	netbsd-8-1-RELEASE:1.1.1.3
	netbsd-8-1-RC1:1.1.1.3
	pgoyette-compat-merge-20190127:1.1.1.4
	pgoyette-compat-20190127:1.1.1.4
	pgoyette-compat-20190118:1.1.1.4
	pgoyette-compat-1226:1.1.1.4
	pgoyette-compat-1126:1.1.1.4
	pgoyette-compat-1020:1.1.1.4
	pgoyette-compat-0930:1.1.1.4
	pgoyette-compat-0906:1.1.1.4
	netbsd-7-2-RELEASE:1.1.1.2
	pgoyette-compat-0728:1.1.1.4
	clang-337282:1.1.1.4
	netbsd-8-0-RELEASE:1.1.1.3
	phil-wifi:1.1.1.4.0.4
	phil-wifi-base:1.1.1.4
	pgoyette-compat-0625:1.1.1.4
	netbsd-8-0-RC2:1.1.1.3
	pgoyette-compat-0521:1.1.1.4
	pgoyette-compat-0502:1.1.1.4
	pgoyette-compat-0422:1.1.1.4
	netbsd-8-0-RC1:1.1.1.3
	pgoyette-compat-0415:1.1.1.4
	pgoyette-compat-0407:1.1.1.4
	pgoyette-compat-0330:1.1.1.4
	pgoyette-compat-0322:1.1.1.4
	pgoyette-compat-0315:1.1.1.4
	netbsd-7-1-2-RELEASE:1.1.1.2
	pgoyette-compat:1.1.1.4.0.2
	pgoyette-compat-base:1.1.1.4
	netbsd-7-1-1-RELEASE:1.1.1.2
	clang-319952:1.1.1.4
	matt-nb8-mediatek:1.1.1.3.0.12
	matt-nb8-mediatek-base:1.1.1.3
	clang-309604:1.1.1.4
	perseant-stdc-iso10646:1.1.1.3.0.10
	perseant-stdc-iso10646-base:1.1.1.3
	netbsd-8:1.1.1.3.0.8
	netbsd-8-base:1.1.1.3
	prg-localcount2-base3:1.1.1.3
	prg-localcount2-base2:1.1.1.3
	prg-localcount2-base1:1.1.1.3
	prg-localcount2:1.1.1.3.0.6
	prg-localcount2-base:1.1.1.3
	pgoyette-localcount-20170426:1.1.1.3
	bouyer-socketcan-base1:1.1.1.3
	pgoyette-localcount-20170320:1.1.1.3
	netbsd-7-1:1.1.1.2.0.10
	netbsd-7-1-RELEASE:1.1.1.2
	netbsd-7-1-RC2:1.1.1.2
	clang-294123:1.1.1.3
	netbsd-7-nhusb-base-20170116:1.1.1.2
	bouyer-socketcan:1.1.1.3.0.4
	bouyer-socketcan-base:1.1.1.3
	clang-291444:1.1.1.3
	pgoyette-localcount-20170107:1.1.1.3
	netbsd-7-1-RC1:1.1.1.2
	pgoyette-localcount-20161104:1.1.1.3
	netbsd-7-0-2-RELEASE:1.1.1.2
	localcount-20160914:1.1.1.3
	netbsd-7-nhusb:1.1.1.2.0.8
	netbsd-7-nhusb-base:1.1.1.2
	clang-280599:1.1.1.3
	pgoyette-localcount-20160806:1.1.1.3
	pgoyette-localcount-20160726:1.1.1.3
	pgoyette-localcount:1.1.1.3.0.2
	pgoyette-localcount-base:1.1.1.3
	netbsd-7-0-1-RELEASE:1.1.1.2
	clang-261930:1.1.1.3
	netbsd-7-0:1.1.1.2.0.6
	netbsd-7-0-RELEASE:1.1.1.2
	netbsd-7-0-RC3:1.1.1.2
	netbsd-7-0-RC2:1.1.1.2
	netbsd-7-0-RC1:1.1.1.2
	clang-237755:1.1.1.2
	clang-232565:1.1.1.2
	clang-227398:1.1.1.2
	tls-maxphys-base:1.1.1.2
	tls-maxphys:1.1.1.2.0.4
	netbsd-7:1.1.1.2.0.2
	netbsd-7-base:1.1.1.2
	clang-215315:1.1.1.2
	clang-209886:1.1.1.2
	yamt-pagecache:1.1.1.1.0.4
	yamt-pagecache-base9:1.1.1.1
	tls-earlyentropy:1.1.1.1.0.2
	tls-earlyentropy-base:1.1.1.2
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.1
	riastradh-drm2-base3:1.1.1.1
	clang-202566:1.1.1.1
	clang-201163:1.1.1.1
	clang-199312:1.1.1.1
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.49;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.49;	author joerg;	state Exp;
branches
	1.1.1.1.2.1
	1.1.1.1.4.1;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.05.30.18.14.40;	author joerg;	state Exp;
branches
	1.1.1.2.4.1;
next	1.1.1.3;
commitid	8q0kdlBlCn09GACx;

1.1.1.3
date	2016.02.27.22.11.52;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	tIimz3oDlh1NpBWy;

1.1.1.4
date	2017.08.01.19.34.57;	author joerg;	state Exp;
branches
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	pMuDy65V0VicSx1A;

1.1.1.5
date	2019.11.13.22.19.20;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.1.2.1
date	2014.08.10.07.08.07;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.1.4.1
date	2013.11.28.14.14.49;	author yamt;	state dead;
branches;
next	1.1.1.1.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.1.4.2
date	2014.05.22.16.18.26;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.2.4.1
date	2014.05.30.18.14.40;	author tls;	state dead;
branches;
next	1.1.1.2.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.2.4.2
date	2014.08.19.23.47.26;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.4.4.1
date	2020.04.13.07.46.30;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/ASTMatchers/Dynamic/Diagnostics.h"

namespace clang {
namespace ast_matchers {
namespace dynamic {

Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
                                                     SourceRange Range) {
  ContextStack.push_back(ContextFrame());
  ContextFrame& data = ContextStack.back();
  data.Type = Type;
  data.Range = Range;
  return ArgStream(&data.Args);
}

Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
                              StringRef MatcherName,
                              const SourceRange &MatcherRange)
    : Error(Error) {
  Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
}

Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
                              StringRef MatcherName,
                              const SourceRange &MatcherRange,
                              unsigned ArgNumber)
    : Error(Error) {
  Error->pushContextFrame(CT_MatcherArg, MatcherRange) << ArgNumber
                                                       << MatcherName;
}

Diagnostics::Context::~Context() { Error->ContextStack.pop_back(); }

Diagnostics::OverloadContext::OverloadContext(Diagnostics *Error)
    : Error(Error), BeginIndex(Error->Errors.size()) {}

Diagnostics::OverloadContext::~OverloadContext() {
  // Merge all errors that happened while in this context.
  if (BeginIndex < Error->Errors.size()) {
    Diagnostics::ErrorContent &Dest = Error->Errors[BeginIndex];
    for (size_t i = BeginIndex + 1, e = Error->Errors.size(); i < e; ++i) {
      Dest.Messages.push_back(Error->Errors[i].Messages[0]);
    }
    Error->Errors.resize(BeginIndex + 1);
  }
}

void Diagnostics::OverloadContext::revertErrors() {
  // Revert the errors.
  Error->Errors.resize(BeginIndex);
}

Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
  Out->push_back(Arg.str());
  return *this;
}

Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
                                             ErrorType Error) {
  Errors.push_back(ErrorContent());
  ErrorContent &Last = Errors.back();
  Last.ContextStack = ContextStack;
  Last.Messages.push_back(ErrorContent::Message());
  Last.Messages.back().Range = Range;
  Last.Messages.back().Type = Error;
  return ArgStream(&Last.Messages.back().Args);
}

StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
  switch (Type) {
    case Diagnostics::CT_MatcherConstruct:
      return "Error building matcher $0.";
    case Diagnostics::CT_MatcherArg:
      return "Error parsing argument $0 for matcher $1.";
  }
  llvm_unreachable("Unknown ContextType value.");
}

StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
  switch (Type) {
  case Diagnostics::ET_RegistryNotFound:
    return "Matcher not found: $0";
  case Diagnostics::ET_RegistryWrongArgCount:
    return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
  case Diagnostics::ET_RegistryWrongArgType:
    return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
  case Diagnostics::ET_RegistryNotBindable:
    return "Matcher does not support binding.";
  case Diagnostics::ET_RegistryAmbiguousOverload:
    // TODO: Add type info about the overload error.
    return "Ambiguous matcher overload.";

  case Diagnostics::ET_ParserStringError:
    return "Error parsing string token: <$0>";
  case Diagnostics::ET_ParserNoOpenParen:
    return "Error parsing matcher. Found token <$0> while looking for '('.";
  case Diagnostics::ET_ParserNoCloseParen:
    return "Error parsing matcher. Found end-of-code while looking for ')'.";
  case Diagnostics::ET_ParserNoComma:
    return "Error parsing matcher. Found token <$0> while looking for ','.";
  case Diagnostics::ET_ParserNoCode:
    return "End of code found while looking for token.";
  case Diagnostics::ET_ParserNotAMatcher:
    return "Input value is not a matcher expression.";
  case Diagnostics::ET_ParserInvalidToken:
    return "Invalid token <$0> found when looking for a value.";
  case Diagnostics::ET_ParserMalformedBindExpr:
    return "Malformed bind() expression.";
  case Diagnostics::ET_ParserTrailingCode:
    return "Expected end of code.";
  case Diagnostics::ET_ParserUnsignedError:
    return "Error parsing unsigned token: <$0>";
  case Diagnostics::ET_ParserOverloadedType:
    return "Input value has unresolved overloaded type: $0";

  case Diagnostics::ET_None:
    return "<N/A>";
  }
  llvm_unreachable("Unknown ErrorType value.");
}

void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
                       llvm::raw_ostream &OS) {
  while (!FormatString.empty()) {
    std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
    OS << Pieces.first.str();
    if (Pieces.second.empty()) break;

    const char Next = Pieces.second.front();
    FormatString = Pieces.second.drop_front();
    if (Next >= '0' && Next <= '9') {
      const unsigned Index = Next - '0';
      if (Index < Args.size()) {
        OS << Args[Index];
      } else {
        OS << "<Argument_Not_Provided>";
      }
    }
  }
}

static void maybeAddLineAndColumn(const SourceRange &Range,
                                  llvm::raw_ostream &OS) {
  if (Range.Start.Line > 0 && Range.Start.Column > 0) {
    OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
  }
}

static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
                                      llvm::raw_ostream &OS) {
  maybeAddLineAndColumn(Frame.Range, OS);
  formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
}

static void
printMessageToStream(const Diagnostics::ErrorContent::Message &Message,
                     const Twine Prefix, llvm::raw_ostream &OS) {
  maybeAddLineAndColumn(Message.Range, OS);
  OS << Prefix;
  formatErrorString(errorTypeToFormatString(Message.Type), Message.Args, OS);
}

static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
                                      llvm::raw_ostream &OS) {
  if (Content.Messages.size() == 1) {
    printMessageToStream(Content.Messages[0], "", OS);
  } else {
    for (size_t i = 0, e = Content.Messages.size(); i != e; ++i) {
      if (i != 0) OS << "\n";
      printMessageToStream(Content.Messages[i],
                           "Candidate " + Twine(i + 1) + ": ", OS);
    }
  }
}

void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
  for (size_t i = 0, e = Errors.size(); i != e; ++i) {
    if (i != 0) OS << "\n";
    printErrorContentToStream(Errors[i], OS);
  }
}

std::string Diagnostics::toString() const {
  std::string S;
  llvm::raw_string_ostream OS(S);
  printToStream(OS);
  return OS.str();
}

void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
  for (size_t i = 0, e = Errors.size(); i != e; ++i) {
    if (i != 0) OS << "\n";
    const ErrorContent &Error = Errors[i];
    for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++i) {
      printContextFrameToStream(Error.ContextStack[i], OS);
      OS << "\n";
    }
    printErrorContentToStream(Error, OS);
  }
}

std::string Diagnostics::toStringFull() const {
  std::string S;
  llvm::raw_string_ostream OS(S);
  printToStreamFull(OS);
  return OS.str();
}

}  // namespace dynamic
}  // namespace ast_matchers
}  // namespace clang
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.1.2.1
log
@Rebase.
@
text
@d90 1
a90 1
  case Diagnostics::ET_RegistryMatcherNotFound:
a100 2
  case Diagnostics::ET_RegistryValueNotFound:
    return "Value not found: $0";
@


1.1.1.2
log
@Import Clang 3.5svn r209886.
@
text
@d90 1
a90 1
  case Diagnostics::ET_RegistryMatcherNotFound:
a100 2
  case Diagnostics::ET_RegistryValueNotFound:
    return "Value not found: $0";
@


1.1.1.3
log
@Import Clang 3.8.0rc3 r261930.
@
text
@d15 1
d18 1
a18 1
  ContextStack.emplace_back();
d27 1
a27 1
                              SourceRange MatcherRange)
d34 1
a34 1
                              SourceRange MatcherRange,
d67 1
a67 1
Diagnostics::ArgStream Diagnostics::addError(SourceRange Range,
d69 1
a69 1
  Errors.emplace_back();
d72 1
a72 1
  Last.Messages.emplace_back();
d78 1
a78 1
static StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
d88 1
a88 1
static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
d133 2
a134 3
static void formatErrorString(StringRef FormatString,
                              ArrayRef<std::string> Args,
                              llvm::raw_ostream &OS) {
d153 1
a153 1
static void maybeAddLineAndColumn(SourceRange Range,
@


1.1.1.4
log
@Import clang r309604 from branches/release_50
@
text
@d121 2
a122 2
  case Diagnostics::ET_ParserNumberError:
    return "Error parsing numeric literal: <$0>";
@


1.1.1.4.4.1
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.5
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.2.4.1
log
@file Diagnostics.cpp was added on branch tls-maxphys on 2014-08-19 23:47:26 +0000
@
text
@d1 222
@


1.1.1.2.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 222
//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/ASTMatchers/Dynamic/Diagnostics.h"

namespace clang {
namespace ast_matchers {
namespace dynamic {

Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
                                                     SourceRange Range) {
  ContextStack.push_back(ContextFrame());
  ContextFrame& data = ContextStack.back();
  data.Type = Type;
  data.Range = Range;
  return ArgStream(&data.Args);
}

Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
                              StringRef MatcherName,
                              const SourceRange &MatcherRange)
    : Error(Error) {
  Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
}

Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
                              StringRef MatcherName,
                              const SourceRange &MatcherRange,
                              unsigned ArgNumber)
    : Error(Error) {
  Error->pushContextFrame(CT_MatcherArg, MatcherRange) << ArgNumber
                                                       << MatcherName;
}

Diagnostics::Context::~Context() { Error->ContextStack.pop_back(); }

Diagnostics::OverloadContext::OverloadContext(Diagnostics *Error)
    : Error(Error), BeginIndex(Error->Errors.size()) {}

Diagnostics::OverloadContext::~OverloadContext() {
  // Merge all errors that happened while in this context.
  if (BeginIndex < Error->Errors.size()) {
    Diagnostics::ErrorContent &Dest = Error->Errors[BeginIndex];
    for (size_t i = BeginIndex + 1, e = Error->Errors.size(); i < e; ++i) {
      Dest.Messages.push_back(Error->Errors[i].Messages[0]);
    }
    Error->Errors.resize(BeginIndex + 1);
  }
}

void Diagnostics::OverloadContext::revertErrors() {
  // Revert the errors.
  Error->Errors.resize(BeginIndex);
}

Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
  Out->push_back(Arg.str());
  return *this;
}

Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
                                             ErrorType Error) {
  Errors.push_back(ErrorContent());
  ErrorContent &Last = Errors.back();
  Last.ContextStack = ContextStack;
  Last.Messages.push_back(ErrorContent::Message());
  Last.Messages.back().Range = Range;
  Last.Messages.back().Type = Error;
  return ArgStream(&Last.Messages.back().Args);
}

StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
  switch (Type) {
    case Diagnostics::CT_MatcherConstruct:
      return "Error building matcher $0.";
    case Diagnostics::CT_MatcherArg:
      return "Error parsing argument $0 for matcher $1.";
  }
  llvm_unreachable("Unknown ContextType value.");
}

StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
  switch (Type) {
  case Diagnostics::ET_RegistryMatcherNotFound:
    return "Matcher not found: $0";
  case Diagnostics::ET_RegistryWrongArgCount:
    return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
  case Diagnostics::ET_RegistryWrongArgType:
    return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
  case Diagnostics::ET_RegistryNotBindable:
    return "Matcher does not support binding.";
  case Diagnostics::ET_RegistryAmbiguousOverload:
    // TODO: Add type info about the overload error.
    return "Ambiguous matcher overload.";
  case Diagnostics::ET_RegistryValueNotFound:
    return "Value not found: $0";

  case Diagnostics::ET_ParserStringError:
    return "Error parsing string token: <$0>";
  case Diagnostics::ET_ParserNoOpenParen:
    return "Error parsing matcher. Found token <$0> while looking for '('.";
  case Diagnostics::ET_ParserNoCloseParen:
    return "Error parsing matcher. Found end-of-code while looking for ')'.";
  case Diagnostics::ET_ParserNoComma:
    return "Error parsing matcher. Found token <$0> while looking for ','.";
  case Diagnostics::ET_ParserNoCode:
    return "End of code found while looking for token.";
  case Diagnostics::ET_ParserNotAMatcher:
    return "Input value is not a matcher expression.";
  case Diagnostics::ET_ParserInvalidToken:
    return "Invalid token <$0> found when looking for a value.";
  case Diagnostics::ET_ParserMalformedBindExpr:
    return "Malformed bind() expression.";
  case Diagnostics::ET_ParserTrailingCode:
    return "Expected end of code.";
  case Diagnostics::ET_ParserUnsignedError:
    return "Error parsing unsigned token: <$0>";
  case Diagnostics::ET_ParserOverloadedType:
    return "Input value has unresolved overloaded type: $0";

  case Diagnostics::ET_None:
    return "<N/A>";
  }
  llvm_unreachable("Unknown ErrorType value.");
}

void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
                       llvm::raw_ostream &OS) {
  while (!FormatString.empty()) {
    std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
    OS << Pieces.first.str();
    if (Pieces.second.empty()) break;

    const char Next = Pieces.second.front();
    FormatString = Pieces.second.drop_front();
    if (Next >= '0' && Next <= '9') {
      const unsigned Index = Next - '0';
      if (Index < Args.size()) {
        OS << Args[Index];
      } else {
        OS << "<Argument_Not_Provided>";
      }
    }
  }
}

static void maybeAddLineAndColumn(const SourceRange &Range,
                                  llvm::raw_ostream &OS) {
  if (Range.Start.Line > 0 && Range.Start.Column > 0) {
    OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
  }
}

static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
                                      llvm::raw_ostream &OS) {
  maybeAddLineAndColumn(Frame.Range, OS);
  formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
}

static void
printMessageToStream(const Diagnostics::ErrorContent::Message &Message,
                     const Twine Prefix, llvm::raw_ostream &OS) {
  maybeAddLineAndColumn(Message.Range, OS);
  OS << Prefix;
  formatErrorString(errorTypeToFormatString(Message.Type), Message.Args, OS);
}

static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
                                      llvm::raw_ostream &OS) {
  if (Content.Messages.size() == 1) {
    printMessageToStream(Content.Messages[0], "", OS);
  } else {
    for (size_t i = 0, e = Content.Messages.size(); i != e; ++i) {
      if (i != 0) OS << "\n";
      printMessageToStream(Content.Messages[i],
                           "Candidate " + Twine(i + 1) + ": ", OS);
    }
  }
}

void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
  for (size_t i = 0, e = Errors.size(); i != e; ++i) {
    if (i != 0) OS << "\n";
    printErrorContentToStream(Errors[i], OS);
  }
}

std::string Diagnostics::toString() const {
  std::string S;
  llvm::raw_string_ostream OS(S);
  printToStream(OS);
  return OS.str();
}

void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
  for (size_t i = 0, e = Errors.size(); i != e; ++i) {
    if (i != 0) OS << "\n";
    const ErrorContent &Error = Errors[i];
    for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++i) {
      printContextFrameToStream(Error.ContextStack[i], OS);
      OS << "\n";
    }
    printErrorContentToStream(Error, OS);
  }
}

std::string Diagnostics::toStringFull() const {
  std::string S;
  llvm::raw_string_ostream OS(S);
  printToStreamFull(OS);
  return OS.str();
}

}  // namespace dynamic
}  // namespace ast_matchers
}  // namespace clang
@


1.1.1.1.4.1
log
@file Diagnostics.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:26 +0000
@
text
@d1 220
@


1.1.1.1.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 220
//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/ASTMatchers/Dynamic/Diagnostics.h"

namespace clang {
namespace ast_matchers {
namespace dynamic {

Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
                                                     SourceRange Range) {
  ContextStack.push_back(ContextFrame());
  ContextFrame& data = ContextStack.back();
  data.Type = Type;
  data.Range = Range;
  return ArgStream(&data.Args);
}

Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
                              StringRef MatcherName,
                              const SourceRange &MatcherRange)
    : Error(Error) {
  Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
}

Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
                              StringRef MatcherName,
                              const SourceRange &MatcherRange,
                              unsigned ArgNumber)
    : Error(Error) {
  Error->pushContextFrame(CT_MatcherArg, MatcherRange) << ArgNumber
                                                       << MatcherName;
}

Diagnostics::Context::~Context() { Error->ContextStack.pop_back(); }

Diagnostics::OverloadContext::OverloadContext(Diagnostics *Error)
    : Error(Error), BeginIndex(Error->Errors.size()) {}

Diagnostics::OverloadContext::~OverloadContext() {
  // Merge all errors that happened while in this context.
  if (BeginIndex < Error->Errors.size()) {
    Diagnostics::ErrorContent &Dest = Error->Errors[BeginIndex];
    for (size_t i = BeginIndex + 1, e = Error->Errors.size(); i < e; ++i) {
      Dest.Messages.push_back(Error->Errors[i].Messages[0]);
    }
    Error->Errors.resize(BeginIndex + 1);
  }
}

void Diagnostics::OverloadContext::revertErrors() {
  // Revert the errors.
  Error->Errors.resize(BeginIndex);
}

Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
  Out->push_back(Arg.str());
  return *this;
}

Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
                                             ErrorType Error) {
  Errors.push_back(ErrorContent());
  ErrorContent &Last = Errors.back();
  Last.ContextStack = ContextStack;
  Last.Messages.push_back(ErrorContent::Message());
  Last.Messages.back().Range = Range;
  Last.Messages.back().Type = Error;
  return ArgStream(&Last.Messages.back().Args);
}

StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
  switch (Type) {
    case Diagnostics::CT_MatcherConstruct:
      return "Error building matcher $0.";
    case Diagnostics::CT_MatcherArg:
      return "Error parsing argument $0 for matcher $1.";
  }
  llvm_unreachable("Unknown ContextType value.");
}

StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
  switch (Type) {
  case Diagnostics::ET_RegistryNotFound:
    return "Matcher not found: $0";
  case Diagnostics::ET_RegistryWrongArgCount:
    return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
  case Diagnostics::ET_RegistryWrongArgType:
    return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
  case Diagnostics::ET_RegistryNotBindable:
    return "Matcher does not support binding.";
  case Diagnostics::ET_RegistryAmbiguousOverload:
    // TODO: Add type info about the overload error.
    return "Ambiguous matcher overload.";

  case Diagnostics::ET_ParserStringError:
    return "Error parsing string token: <$0>";
  case Diagnostics::ET_ParserNoOpenParen:
    return "Error parsing matcher. Found token <$0> while looking for '('.";
  case Diagnostics::ET_ParserNoCloseParen:
    return "Error parsing matcher. Found end-of-code while looking for ')'.";
  case Diagnostics::ET_ParserNoComma:
    return "Error parsing matcher. Found token <$0> while looking for ','.";
  case Diagnostics::ET_ParserNoCode:
    return "End of code found while looking for token.";
  case Diagnostics::ET_ParserNotAMatcher:
    return "Input value is not a matcher expression.";
  case Diagnostics::ET_ParserInvalidToken:
    return "Invalid token <$0> found when looking for a value.";
  case Diagnostics::ET_ParserMalformedBindExpr:
    return "Malformed bind() expression.";
  case Diagnostics::ET_ParserTrailingCode:
    return "Expected end of code.";
  case Diagnostics::ET_ParserUnsignedError:
    return "Error parsing unsigned token: <$0>";
  case Diagnostics::ET_ParserOverloadedType:
    return "Input value has unresolved overloaded type: $0";

  case Diagnostics::ET_None:
    return "<N/A>";
  }
  llvm_unreachable("Unknown ErrorType value.");
}

void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
                       llvm::raw_ostream &OS) {
  while (!FormatString.empty()) {
    std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
    OS << Pieces.first.str();
    if (Pieces.second.empty()) break;

    const char Next = Pieces.second.front();
    FormatString = Pieces.second.drop_front();
    if (Next >= '0' && Next <= '9') {
      const unsigned Index = Next - '0';
      if (Index < Args.size()) {
        OS << Args[Index];
      } else {
        OS << "<Argument_Not_Provided>";
      }
    }
  }
}

static void maybeAddLineAndColumn(const SourceRange &Range,
                                  llvm::raw_ostream &OS) {
  if (Range.Start.Line > 0 && Range.Start.Column > 0) {
    OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
  }
}

static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
                                      llvm::raw_ostream &OS) {
  maybeAddLineAndColumn(Frame.Range, OS);
  formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
}

static void
printMessageToStream(const Diagnostics::ErrorContent::Message &Message,
                     const Twine Prefix, llvm::raw_ostream &OS) {
  maybeAddLineAndColumn(Message.Range, OS);
  OS << Prefix;
  formatErrorString(errorTypeToFormatString(Message.Type), Message.Args, OS);
}

static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
                                      llvm::raw_ostream &OS) {
  if (Content.Messages.size() == 1) {
    printMessageToStream(Content.Messages[0], "", OS);
  } else {
    for (size_t i = 0, e = Content.Messages.size(); i != e; ++i) {
      if (i != 0) OS << "\n";
      printMessageToStream(Content.Messages[i],
                           "Candidate " + Twine(i + 1) + ": ", OS);
    }
  }
}

void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
  for (size_t i = 0, e = Errors.size(); i != e; ++i) {
    if (i != 0) OS << "\n";
    printErrorContentToStream(Errors[i], OS);
  }
}

std::string Diagnostics::toString() const {
  std::string S;
  llvm::raw_string_ostream OS(S);
  printToStream(OS);
  return OS.str();
}

void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
  for (size_t i = 0, e = Errors.size(); i != e; ++i) {
    if (i != 0) OS << "\n";
    const ErrorContent &Error = Errors[i];
    for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++i) {
      printContextFrameToStream(Error.ContextStack[i], OS);
      OS << "\n";
    }
    printErrorContentToStream(Error, OS);
  }
}

std::string Diagnostics::toStringFull() const {
  std::string S;
  llvm::raw_string_ostream OS(S);
  printToStreamFull(OS);
  return OS.str();
}

}  // namespace dynamic
}  // namespace ast_matchers
}  // namespace clang
@


