summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic')
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp220
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h453
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp420
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp345
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp256
5 files changed, 1694 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
new file mode 100644
index 0000000..da2ed9a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -0,0 +1,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
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
new file mode 100644
index 0000000..ae0c300
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -0,0 +1,453 @@
+//===--- Marshallers.h - Generic matcher function marshallers -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Functions templates and classes to wrap matcher construct functions.
+///
+/// A collection of template function and classes that provide a generic
+/// marshalling layer on top of matcher construct functions.
+/// These are used by the registry to export all marshaller constructors with
+/// the same generic interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
+
+#include <string>
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+namespace internal {
+
+/// \brief Helper template class to just from argument type to the right is/get
+/// functions in VariantValue.
+/// Used to verify and extract the matcher arguments below.
+template <class T> struct ArgTypeTraits;
+template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
+};
+
+template <> struct ArgTypeTraits<std::string> {
+ static StringRef asString() { return "String"; }
+ static bool is(const VariantValue &Value) { return Value.isString(); }
+ static const std::string &get(const VariantValue &Value) {
+ return Value.getString();
+ }
+};
+
+template <>
+struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> {
+};
+
+template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
+ static std::string asString() {
+ return (Twine("Matcher<") +
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() +
+ ">").str();
+ }
+ static bool is(const VariantValue &Value) {
+ return Value.isMatcher() && Value.getMatcher().hasTypedMatcher<T>();
+ }
+ static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
+ return Value.getMatcher().getTypedMatcher<T>();
+ }
+};
+
+template <> struct ArgTypeTraits<unsigned> {
+ static std::string asString() { return "Unsigned"; }
+ static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
+ static unsigned get(const VariantValue &Value) {
+ return Value.getUnsigned();
+ }
+};
+
+/// \brief Generic MatcherCreate interface.
+///
+/// Provides a \c run() method that constructs the matcher from the provided
+/// arguments.
+class MatcherCreateCallback {
+public:
+ virtual ~MatcherCreateCallback() {}
+ virtual VariantMatcher run(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const = 0;
+};
+
+/// \brief Simple callback implementation. Marshaller and function are provided.
+///
+/// This class wraps a function of arbitrary signature and a marshaller
+/// function into a MatcherCreateCallback.
+/// The marshaller is in charge of taking the VariantValue arguments, checking
+/// their types, unpacking them and calling the underlying function.
+class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ typedef VariantMatcher (*MarshallerType)(void (*Func)(),
+ StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+ /// \param Marshaller Function to unpack the arguments and call \c Func
+ /// \param Func Matcher construct function. This is the function that
+ /// compile-time matcher expressions would use to create the matcher.
+ FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, void (*Func)(),
+ StringRef MatcherName)
+ : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName) {}
+
+ VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ return Marshaller(Func, MatcherName, NameRange, Args, Error);
+ }
+
+private:
+ const MarshallerType Marshaller;
+ void (* const Func)();
+ const std::string MatcherName;
+};
+
+/// \brief Simple callback implementation. Free function is wrapped.
+///
+/// This class simply wraps a free function with the right signature to export
+/// it as a MatcherCreateCallback.
+/// This allows us to have one implementation of the interface for as many free
+/// functions as we want, reducing the number of symbols and size of the
+/// object file.
+class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ typedef VariantMatcher (*RunFunc)(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+ FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
+ : Func(Func), MatcherName(MatcherName.str()) {}
+
+ VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ return Func(MatcherName, NameRange, Args, Error);
+ }
+
+private:
+ const RunFunc Func;
+ const std::string MatcherName;
+};
+
+/// \brief Helper macros to check the arguments on all marshaller functions.
+#define CHECK_ARG_COUNT(count) \
+ if (Args.size() != count) { \
+ Error->addError(NameRange, Error->ET_RegistryWrongArgCount) \
+ << count << Args.size(); \
+ return VariantMatcher(); \
+ }
+
+#define CHECK_ARG_TYPE(index, type) \
+ if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
+ Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \
+ << (index + 1) << ArgTypeTraits<type>::asString() \
+ << Args[index].Value.getTypeAsString(); \
+ return VariantMatcher(); \
+ }
+
+/// \brief Helper methods to extract and merge all possible typed matchers
+/// out of the polymorphic object.
+template <class PolyMatcher>
+static void mergePolyMatchers(const PolyMatcher &Poly,
+ std::vector<DynTypedMatcher> &Out,
+ ast_matchers::internal::EmptyTypeList) {}
+
+template <class PolyMatcher, class TypeList>
+static void mergePolyMatchers(const PolyMatcher &Poly,
+ std::vector<DynTypedMatcher> &Out, TypeList) {
+ Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly));
+ mergePolyMatchers(Poly, Out, typename TypeList::tail());
+}
+
+/// \brief Convert the return values of the functions into a VariantMatcher.
+///
+/// There are 2 cases right now: The return value is a Matcher<T> or is a
+/// polymorphic matcher. For the former, we just construct the VariantMatcher.
+/// For the latter, we instantiate all the possible Matcher<T> of the poly
+/// matcher.
+static VariantMatcher outvalueToVariantMatcher(const DynTypedMatcher &Matcher) {
+ return VariantMatcher::SingleMatcher(Matcher);
+}
+
+template <typename T>
+static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher,
+ typename T::ReturnTypes * =
+ NULL) {
+ std::vector<DynTypedMatcher> Matchers;
+ mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes());
+ VariantMatcher Out = VariantMatcher::PolymorphicMatcher(Matchers);
+ return Out;
+}
+
+/// \brief 0-arg marshaller function.
+template <typename ReturnType>
+static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ typedef ReturnType (*FuncType)();
+ CHECK_ARG_COUNT(0);
+ return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)());
+}
+
+/// \brief 1-arg marshaller function.
+template <typename ReturnType, typename ArgType1>
+static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ typedef ReturnType (*FuncType)(ArgType1);
+ CHECK_ARG_COUNT(1);
+ CHECK_ARG_TYPE(0, ArgType1);
+ return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)(
+ ArgTypeTraits<ArgType1>::get(Args[0].Value)));
+}
+
+/// \brief 2-arg marshaller function.
+template <typename ReturnType, typename ArgType1, typename ArgType2>
+static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ typedef ReturnType (*FuncType)(ArgType1, ArgType2);
+ CHECK_ARG_COUNT(2);
+ CHECK_ARG_TYPE(0, ArgType1);
+ CHECK_ARG_TYPE(1, ArgType2);
+ return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)(
+ ArgTypeTraits<ArgType1>::get(Args[0].Value),
+ ArgTypeTraits<ArgType2>::get(Args[1].Value)));
+}
+
+#undef CHECK_ARG_COUNT
+#undef CHECK_ARG_TYPE
+
+/// \brief Variadic marshaller function.
+template <typename ResultT, typename ArgT,
+ ResultT (*Func)(ArrayRef<const ArgT *>)>
+VariantMatcher
+variadicMatcherCreateCallback(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) {
+ ArgT **InnerArgs = new ArgT *[Args.size()]();
+
+ bool HasError = false;
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ typedef ArgTypeTraits<ArgT> ArgTraits;
+ const ParserValue &Arg = Args[i];
+ const VariantValue &Value = Arg.Value;
+ if (!ArgTraits::is(Value)) {
+ Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
+ << (i + 1) << ArgTraits::asString() << Value.getTypeAsString();
+ HasError = true;
+ break;
+ }
+ InnerArgs[i] = new ArgT(ArgTraits::get(Value));
+ }
+
+ VariantMatcher Out;
+ if (!HasError) {
+ Out = outvalueToVariantMatcher(
+ Func(ArrayRef<const ArgT *>(InnerArgs, Args.size())));
+ }
+
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ delete InnerArgs[i];
+ }
+ delete[] InnerArgs;
+ return Out;
+}
+
+/// \brief Helper class used to collect all the possible overloads of an
+/// argument adaptative matcher function.
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+ typename FromTypes, typename ToTypes>
+class AdaptativeOverloadCollector {
+public:
+ AdaptativeOverloadCollector(StringRef Name,
+ std::vector<MatcherCreateCallback *> &Out)
+ : Name(Name), Out(Out) {
+ collect(FromTypes());
+ }
+
+private:
+ typedef ast_matchers::internal::ArgumentAdaptingMatcherFunc<
+ ArgumentAdapterT, FromTypes, ToTypes> AdaptativeFunc;
+
+ /// \brief End case for the recursion
+ static void collect(ast_matchers::internal::EmptyTypeList) {}
+
+ /// \brief Recursive case. Get the overload for the head of the list, and
+ /// recurse to the tail.
+ template <typename FromTypeList> inline void collect(FromTypeList);
+
+ const StringRef Name;
+ std::vector<MatcherCreateCallback *> &Out;
+};
+
+/// \brief MatcherCreateCallback that wraps multiple "overloads" of the same
+/// matcher.
+///
+/// It will try every overload and generate appropriate errors for when none or
+/// more than one overloads match the arguments.
+class OverloadedMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ OverloadedMatcherCreateCallback(ArrayRef<MatcherCreateCallback *> Callbacks)
+ : Overloads(Callbacks) {}
+
+ virtual ~OverloadedMatcherCreateCallback() {
+ llvm::DeleteContainerPointers(Overloads);
+ }
+
+ virtual VariantMatcher run(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ std::vector<VariantMatcher> Constructed;
+ Diagnostics::OverloadContext Ctx(Error);
+ for (size_t i = 0, e = Overloads.size(); i != e; ++i) {
+ VariantMatcher SubMatcher = Overloads[i]->run(NameRange, Args, Error);
+ if (!SubMatcher.isNull()) {
+ Constructed.push_back(SubMatcher);
+ }
+ }
+
+ if (Constructed.empty()) return VariantMatcher(); // No overload matched.
+ // We ignore the errors if any matcher succeeded.
+ Ctx.revertErrors();
+ if (Constructed.size() > 1) {
+ // More than one constructed. It is ambiguous.
+ Error->addError(NameRange, Error->ET_RegistryAmbiguousOverload);
+ return VariantMatcher();
+ }
+ return Constructed[0];
+ }
+
+private:
+ std::vector<MatcherCreateCallback *> Overloads;
+};
+
+/// \brief Variadic operator marshaller function.
+class VariadicOperatorMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ typedef ast_matchers::internal::VariadicOperatorFunction VarFunc;
+ VariadicOperatorMatcherCreateCallback(VarFunc Func, StringRef MatcherName)
+ : Func(Func), MatcherName(MatcherName) {}
+
+ virtual VariantMatcher run(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ std::vector<VariantMatcher> InnerArgs;
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ const ParserValue &Arg = Args[i];
+ const VariantValue &Value = Arg.Value;
+ if (!Value.isMatcher()) {
+ Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
+ << (i + 1) << "Matcher<>" << Value.getTypeAsString();
+ return VariantMatcher();
+ }
+ InnerArgs.push_back(Value.getMatcher());
+ }
+ return VariantMatcher::VariadicOperatorMatcher(Func, InnerArgs);
+ }
+
+private:
+ const VarFunc Func;
+ const StringRef MatcherName;
+};
+
+
+/// Helper functions to select the appropriate marshaller functions.
+/// They detect the number of arguments, arguments types and return type.
+
+/// \brief 0-arg overload
+template <typename ReturnType>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
+ StringRef MatcherName) {
+ return new FixedArgCountMatcherCreateCallback(
+ matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func),
+ MatcherName);
+}
+
+/// \brief 1-arg overload
+template <typename ReturnType, typename ArgType1>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
+ StringRef MatcherName) {
+ return new FixedArgCountMatcherCreateCallback(
+ matcherMarshall1<ReturnType, ArgType1>,
+ reinterpret_cast<void (*)()>(Func), MatcherName);
+}
+
+/// \brief 2-arg overload
+template <typename ReturnType, typename ArgType1, typename ArgType2>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
+ ArgType2),
+ StringRef MatcherName) {
+ return new FixedArgCountMatcherCreateCallback(
+ matcherMarshall2<ReturnType, ArgType1, ArgType2>,
+ reinterpret_cast<void (*)()>(Func), MatcherName);
+}
+
+/// \brief Variadic overload.
+template <typename ResultT, typename ArgT,
+ ResultT (*Func)(ArrayRef<const ArgT *>)>
+MatcherCreateCallback *
+makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc,
+ StringRef MatcherName) {
+ return new FreeFuncMatcherCreateCallback(
+ &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName);
+}
+
+/// \brief Argument adaptative overload.
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+ typename FromTypes, typename ToTypes>
+MatcherCreateCallback *
+makeMatcherAutoMarshall(ast_matchers::internal::ArgumentAdaptingMatcherFunc<
+ ArgumentAdapterT, FromTypes, ToTypes>,
+ StringRef MatcherName) {
+ std::vector<MatcherCreateCallback *> Overloads;
+ AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName,
+ Overloads);
+ return new OverloadedMatcherCreateCallback(Overloads);
+}
+
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+ typename FromTypes, typename ToTypes>
+template <typename FromTypeList>
+inline void
+AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>::collect(
+ FromTypeList) {
+ Out.push_back(makeMatcherAutoMarshall(
+ &AdaptativeFunc::template create<typename FromTypeList::head>, Name));
+ collect(typename FromTypeList::tail());
+}
+
+/// \brief Variadic operator overload.
+MatcherCreateCallback *makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicOperatorMatcherFunc Func,
+ StringRef MatcherName) {
+ return new VariadicOperatorMatcherCreateCallback(Func.Func, MatcherName);
+}
+
+} // namespace internal
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
new file mode 100644
index 0000000..df9596e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -0,0 +1,420 @@
+//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Recursive parser implementation for the matcher expression grammar.
+///
+//===----------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "clang/Basic/CharInfo.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Simple structure to hold information for one token from the parser.
+struct Parser::TokenInfo {
+ /// \brief Different possible tokens.
+ enum TokenKind {
+ TK_Eof = 0,
+ TK_OpenParen = 1,
+ TK_CloseParen = 2,
+ TK_Comma = 3,
+ TK_Period = 4,
+ TK_Literal = 5,
+ TK_Ident = 6,
+ TK_InvalidChar = 7,
+ TK_Error = 8
+ };
+
+ /// \brief Some known identifiers.
+ static const char* const ID_Bind;
+
+ TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
+
+ StringRef Text;
+ TokenKind Kind;
+ SourceRange Range;
+ VariantValue Value;
+};
+
+const char* const Parser::TokenInfo::ID_Bind = "bind";
+
+/// \brief Simple tokenizer for the parser.
+class Parser::CodeTokenizer {
+public:
+ explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
+ : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error) {
+ NextToken = getNextToken();
+ }
+
+ /// \brief Returns but doesn't consume the next token.
+ const TokenInfo &peekNextToken() const { return NextToken; }
+
+ /// \brief Consumes and returns the next token.
+ TokenInfo consumeNextToken() {
+ TokenInfo ThisToken = NextToken;
+ NextToken = getNextToken();
+ return ThisToken;
+ }
+
+ TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
+
+private:
+ TokenInfo getNextToken() {
+ consumeWhitespace();
+ TokenInfo Result;
+ Result.Range.Start = currentLocation();
+
+ if (Code.empty()) {
+ Result.Kind = TokenInfo::TK_Eof;
+ Result.Text = "";
+ return Result;
+ }
+
+ switch (Code[0]) {
+ case ',':
+ Result.Kind = TokenInfo::TK_Comma;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+ case '.':
+ Result.Kind = TokenInfo::TK_Period;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+ case '(':
+ Result.Kind = TokenInfo::TK_OpenParen;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+ case ')':
+ Result.Kind = TokenInfo::TK_CloseParen;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+
+ case '"':
+ case '\'':
+ // Parse a string literal.
+ consumeStringLiteral(&Result);
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ // Parse an unsigned literal.
+ consumeUnsignedLiteral(&Result);
+ break;
+
+ default:
+ if (isAlphanumeric(Code[0])) {
+ // Parse an identifier
+ size_t TokenLength = 1;
+ while (TokenLength < Code.size() && isAlphanumeric(Code[TokenLength]))
+ ++TokenLength;
+ Result.Kind = TokenInfo::TK_Ident;
+ Result.Text = Code.substr(0, TokenLength);
+ Code = Code.drop_front(TokenLength);
+ } else {
+ Result.Kind = TokenInfo::TK_InvalidChar;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front(1);
+ }
+ break;
+ }
+
+ Result.Range.End = currentLocation();
+ return Result;
+ }
+
+ /// \brief Consume an unsigned literal.
+ void consumeUnsignedLiteral(TokenInfo *Result) {
+ unsigned Length = 1;
+ if (Code.size() > 1) {
+ // Consume the 'x' or 'b' radix modifier, if present.
+ switch (toLowercase(Code[1])) {
+ case 'x': case 'b': Length = 2;
+ }
+ }
+ while (Length < Code.size() && isHexDigit(Code[Length]))
+ ++Length;
+
+ Result->Text = Code.substr(0, Length);
+ Code = Code.drop_front(Length);
+
+ unsigned Value;
+ if (!Result->Text.getAsInteger(0, Value)) {
+ Result->Kind = TokenInfo::TK_Literal;
+ Result->Value = Value;
+ } else {
+ SourceRange Range;
+ Range.Start = Result->Range.Start;
+ Range.End = currentLocation();
+ Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text;
+ Result->Kind = TokenInfo::TK_Error;
+ }
+ }
+
+ /// \brief Consume a string literal.
+ ///
+ /// \c Code must be positioned at the start of the literal (the opening
+ /// quote). Consumed until it finds the same closing quote character.
+ void consumeStringLiteral(TokenInfo *Result) {
+ bool InEscape = false;
+ const char Marker = Code[0];
+ for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
+ if (InEscape) {
+ InEscape = false;
+ continue;
+ }
+ if (Code[Length] == '\\') {
+ InEscape = true;
+ continue;
+ }
+ if (Code[Length] == Marker) {
+ Result->Kind = TokenInfo::TK_Literal;
+ Result->Text = Code.substr(0, Length + 1);
+ Result->Value = Code.substr(1, Length - 1).str();
+ Code = Code.drop_front(Length + 1);
+ return;
+ }
+ }
+
+ StringRef ErrorText = Code;
+ Code = Code.drop_front(Code.size());
+ SourceRange Range;
+ Range.Start = Result->Range.Start;
+ Range.End = currentLocation();
+ Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
+ Result->Kind = TokenInfo::TK_Error;
+ }
+
+ /// \brief Consume all leading whitespace from \c Code.
+ void consumeWhitespace() {
+ while (!Code.empty() && isWhitespace(Code[0])) {
+ if (Code[0] == '\n') {
+ ++Line;
+ StartOfLine = Code.drop_front();
+ }
+ Code = Code.drop_front();
+ }
+ }
+
+ SourceLocation currentLocation() {
+ SourceLocation Location;
+ Location.Line = Line;
+ Location.Column = Code.data() - StartOfLine.data() + 1;
+ return Location;
+ }
+
+ StringRef Code;
+ StringRef StartOfLine;
+ unsigned Line;
+ Diagnostics *Error;
+ TokenInfo NextToken;
+};
+
+Parser::Sema::~Sema() {}
+
+/// \brief Parse and validate a matcher expression.
+/// \return \c true on success, in which case \c Value has the matcher parsed.
+/// If the input is malformed, or some argument has an error, it
+/// returns \c false.
+bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {
+ const TokenInfo NameToken = Tokenizer->consumeNextToken();
+ assert(NameToken.Kind == TokenInfo::TK_Ident);
+ const TokenInfo OpenToken = Tokenizer->consumeNextToken();
+ if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
+ Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
+ << OpenToken.Text;
+ return false;
+ }
+
+ std::vector<ParserValue> Args;
+ TokenInfo EndToken;
+ while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
+ if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
+ // End of args.
+ EndToken = Tokenizer->consumeNextToken();
+ break;
+ }
+ if (Args.size() > 0) {
+ // We must find a , token to continue.
+ const TokenInfo CommaToken = Tokenizer->consumeNextToken();
+ if (CommaToken.Kind != TokenInfo::TK_Comma) {
+ Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
+ << CommaToken.Text;
+ return false;
+ }
+ }
+
+ Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
+ NameToken.Text, NameToken.Range, Args.size() + 1);
+ ParserValue ArgValue;
+ ArgValue.Text = Tokenizer->peekNextToken().Text;
+ ArgValue.Range = Tokenizer->peekNextToken().Range;
+ if (!parseExpressionImpl(&ArgValue.Value)) return false;
+
+ Args.push_back(ArgValue);
+ }
+
+ if (EndToken.Kind == TokenInfo::TK_Eof) {
+ Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
+ return false;
+ }
+
+ std::string BindID;
+ if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
+ // Parse .bind("foo")
+ Tokenizer->consumeNextToken(); // consume the period.
+ const TokenInfo BindToken = Tokenizer->consumeNextToken();
+ const TokenInfo OpenToken = Tokenizer->consumeNextToken();
+ const TokenInfo IDToken = Tokenizer->consumeNextToken();
+ const TokenInfo CloseToken = Tokenizer->consumeNextToken();
+
+ // TODO: We could use different error codes for each/some to be more
+ // explicit about the syntax error.
+ if (BindToken.Kind != TokenInfo::TK_Ident ||
+ BindToken.Text != TokenInfo::ID_Bind) {
+ Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
+ Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
+ Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
+ Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ BindID = IDToken.Value.getString();
+ }
+
+ // Merge the start and end infos.
+ Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
+ NameToken.Text, NameToken.Range);
+ SourceRange MatcherRange = NameToken.Range;
+ MatcherRange.End = EndToken.Range.End;
+ VariantMatcher Result = S->actOnMatcherExpression(
+ NameToken.Text, MatcherRange, BindID, Args, Error);
+ if (Result.isNull()) return false;
+
+ *Value = Result;
+ return true;
+}
+
+/// \brief Parse an <Expresssion>
+bool Parser::parseExpressionImpl(VariantValue *Value) {
+ switch (Tokenizer->nextTokenKind()) {
+ case TokenInfo::TK_Literal:
+ *Value = Tokenizer->consumeNextToken().Value;
+ return true;
+
+ case TokenInfo::TK_Ident:
+ return parseMatcherExpressionImpl(Value);
+
+ case TokenInfo::TK_Eof:
+ Error->addError(Tokenizer->consumeNextToken().Range,
+ Error->ET_ParserNoCode);
+ return false;
+
+ case TokenInfo::TK_Error:
+ // This error was already reported by the tokenizer.
+ return false;
+
+ case TokenInfo::TK_OpenParen:
+ case TokenInfo::TK_CloseParen:
+ case TokenInfo::TK_Comma:
+ case TokenInfo::TK_Period:
+ case TokenInfo::TK_InvalidChar:
+ const TokenInfo Token = Tokenizer->consumeNextToken();
+ Error->addError(Token.Range, Error->ET_ParserInvalidToken) << Token.Text;
+ return false;
+ }
+
+ llvm_unreachable("Unknown token kind.");
+}
+
+Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
+ Diagnostics *Error)
+ : Tokenizer(Tokenizer), S(S), Error(Error) {}
+
+class RegistrySema : public Parser::Sema {
+public:
+ virtual ~RegistrySema() {}
+ VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ if (BindID.empty()) {
+ return Registry::constructMatcher(MatcherName, NameRange, Args, Error);
+ } else {
+ return Registry::constructBoundMatcher(MatcherName, NameRange, BindID,
+ Args, Error);
+ }
+ }
+};
+
+bool Parser::parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error) {
+ RegistrySema S;
+ return parseExpression(Code, &S, Value, Error);
+}
+
+bool Parser::parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error) {
+ CodeTokenizer Tokenizer(Code, Error);
+ if (!Parser(&Tokenizer, S, Error).parseExpressionImpl(Value)) return false;
+ if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) {
+ Error->addError(Tokenizer.peekNextToken().Range,
+ Error->ET_ParserTrailingCode);
+ return false;
+ }
+ return true;
+}
+
+llvm::Optional<DynTypedMatcher>
+Parser::parseMatcherExpression(StringRef Code, Diagnostics *Error) {
+ RegistrySema S;
+ return parseMatcherExpression(Code, &S, Error);
+}
+
+llvm::Optional<DynTypedMatcher>
+Parser::parseMatcherExpression(StringRef Code, Parser::Sema *S,
+ Diagnostics *Error) {
+ VariantValue Value;
+ if (!parseExpression(Code, S, &Value, Error))
+ return llvm::Optional<DynTypedMatcher>();
+ if (!Value.isMatcher()) {
+ Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
+ return llvm::Optional<DynTypedMatcher>();
+ }
+ llvm::Optional<DynTypedMatcher> Result =
+ Value.getMatcher().getSingleMatcher();
+ if (!Result.hasValue()) {
+ Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
+ << Value.getTypeAsString();
+ }
+ return Result;
+}
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
new file mode 100644
index 0000000..70e956e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -0,0 +1,345 @@
+//===--- Registry.cpp - Matcher registry -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===------------------------------------------------------------===//
+///
+/// \file
+/// \brief Registry map populated at static initialization time.
+///
+//===------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+
+#include <utility>
+
+#include "Marshallers.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ManagedStatic.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+using internal::MatcherCreateCallback;
+
+typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;
+class RegistryMaps {
+public:
+ RegistryMaps();
+ ~RegistryMaps();
+
+ const ConstructorMap &constructors() const { return Constructors; }
+
+private:
+ void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback);
+ ConstructorMap Constructors;
+};
+
+void RegistryMaps::registerMatcher(StringRef MatcherName,
+ MatcherCreateCallback *Callback) {
+ assert(Constructors.find(MatcherName) == Constructors.end());
+ Constructors[MatcherName] = Callback;
+}
+
+#define REGISTER_MATCHER(name) \
+ registerMatcher(#name, internal::makeMatcherAutoMarshall( \
+ ::clang::ast_matchers::name, #name));
+
+#define SPECIFIC_MATCHER_OVERLOAD(name, Id) \
+ static_cast< ::clang::ast_matchers::name##_Type##Id>( \
+ ::clang::ast_matchers::name)
+
+#define REGISTER_OVERLOADED_2(name) \
+ do { \
+ MatcherCreateCallback *Callbacks[] = { \
+ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \
+ #name), \
+ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \
+ #name) \
+ }; \
+ registerMatcher(#name, \
+ new internal::OverloadedMatcherCreateCallback(Callbacks)); \
+ } while (0)
+
+/// \brief Generate a registry map with all the known matchers.
+RegistryMaps::RegistryMaps() {
+ // TODO: Here is the list of the missing matchers, grouped by reason.
+ //
+ // Need Variant/Parser fixes:
+ // ofKind
+ //
+ // Polymorphic + argument overload:
+ // unless
+ // findAll
+ //
+ // Other:
+ // loc
+ // equals
+ // equalsNode
+
+ REGISTER_OVERLOADED_2(callee);
+ REGISTER_OVERLOADED_2(hasPrefix);
+ REGISTER_OVERLOADED_2(hasType);
+ REGISTER_OVERLOADED_2(isDerivedFrom);
+ REGISTER_OVERLOADED_2(isSameOrDerivedFrom);
+ REGISTER_OVERLOADED_2(pointsTo);
+ REGISTER_OVERLOADED_2(references);
+ REGISTER_OVERLOADED_2(thisPointerType);
+
+ REGISTER_MATCHER(accessSpecDecl);
+ REGISTER_MATCHER(alignOfExpr);
+ REGISTER_MATCHER(allOf);
+ REGISTER_MATCHER(anyOf);
+ REGISTER_MATCHER(anything);
+ REGISTER_MATCHER(argumentCountIs);
+ REGISTER_MATCHER(arraySubscriptExpr);
+ REGISTER_MATCHER(arrayType);
+ REGISTER_MATCHER(asString);
+ REGISTER_MATCHER(asmStmt);
+ REGISTER_MATCHER(atomicType);
+ REGISTER_MATCHER(autoType);
+ REGISTER_MATCHER(binaryOperator);
+ REGISTER_MATCHER(bindTemporaryExpr);
+ REGISTER_MATCHER(blockPointerType);
+ REGISTER_MATCHER(boolLiteral);
+ REGISTER_MATCHER(breakStmt);
+ REGISTER_MATCHER(builtinType);
+ REGISTER_MATCHER(cStyleCastExpr);
+ REGISTER_MATCHER(callExpr);
+ REGISTER_MATCHER(castExpr);
+ REGISTER_MATCHER(catchStmt);
+ REGISTER_MATCHER(characterLiteral);
+ REGISTER_MATCHER(classTemplateDecl);
+ REGISTER_MATCHER(classTemplateSpecializationDecl);
+ REGISTER_MATCHER(complexType);
+ REGISTER_MATCHER(compoundLiteralExpr);
+ REGISTER_MATCHER(compoundStmt);
+ REGISTER_MATCHER(conditionalOperator);
+ REGISTER_MATCHER(constCastExpr);
+ REGISTER_MATCHER(constantArrayType);
+ REGISTER_MATCHER(constructExpr);
+ REGISTER_MATCHER(constructorDecl);
+ REGISTER_MATCHER(containsDeclaration);
+ REGISTER_MATCHER(continueStmt);
+ REGISTER_MATCHER(ctorInitializer);
+ REGISTER_MATCHER(decl);
+ REGISTER_MATCHER(declCountIs);
+ REGISTER_MATCHER(declRefExpr);
+ REGISTER_MATCHER(declStmt);
+ REGISTER_MATCHER(defaultArgExpr);
+ REGISTER_MATCHER(deleteExpr);
+ REGISTER_MATCHER(dependentSizedArrayType);
+ REGISTER_MATCHER(destructorDecl);
+ REGISTER_MATCHER(doStmt);
+ REGISTER_MATCHER(dynamicCastExpr);
+ REGISTER_MATCHER(eachOf);
+ REGISTER_MATCHER(elaboratedType);
+ REGISTER_MATCHER(enumConstantDecl);
+ REGISTER_MATCHER(enumDecl);
+ REGISTER_MATCHER(explicitCastExpr);
+ REGISTER_MATCHER(expr);
+ REGISTER_MATCHER(fieldDecl);
+ REGISTER_MATCHER(floatLiteral);
+ REGISTER_MATCHER(forEach);
+ REGISTER_MATCHER(forEachDescendant);
+ REGISTER_MATCHER(forField);
+ REGISTER_MATCHER(forRangeStmt);
+ REGISTER_MATCHER(forStmt);
+ REGISTER_MATCHER(functionDecl);
+ REGISTER_MATCHER(functionTemplateDecl);
+ REGISTER_MATCHER(functionType);
+ REGISTER_MATCHER(functionalCastExpr);
+ REGISTER_MATCHER(gotoStmt);
+ REGISTER_MATCHER(has);
+ REGISTER_MATCHER(hasAncestor);
+ REGISTER_MATCHER(hasAnyArgument);
+ REGISTER_MATCHER(hasAnyConstructorInitializer);
+ REGISTER_MATCHER(hasAnyParameter);
+ REGISTER_MATCHER(hasAnySubstatement);
+ REGISTER_MATCHER(hasAnyTemplateArgument);
+ REGISTER_MATCHER(hasAnyUsingShadowDecl);
+ REGISTER_MATCHER(hasArgument);
+ REGISTER_MATCHER(hasArgumentOfType);
+ REGISTER_MATCHER(hasBase);
+ REGISTER_MATCHER(hasBody);
+ REGISTER_MATCHER(hasCanonicalType);
+ REGISTER_MATCHER(hasCondition);
+ REGISTER_MATCHER(hasConditionVariableStatement);
+ REGISTER_MATCHER(hasDeclContext);
+ REGISTER_MATCHER(hasDeclaration);
+ REGISTER_MATCHER(hasDeducedType);
+ REGISTER_MATCHER(hasDescendant);
+ REGISTER_MATCHER(hasDestinationType);
+ REGISTER_MATCHER(hasEitherOperand);
+ REGISTER_MATCHER(hasElementType);
+ REGISTER_MATCHER(hasFalseExpression);
+ REGISTER_MATCHER(hasImplicitDestinationType);
+ REGISTER_MATCHER(hasIncrement);
+ REGISTER_MATCHER(hasIndex);
+ REGISTER_MATCHER(hasInitializer);
+ REGISTER_MATCHER(hasLHS);
+ REGISTER_MATCHER(hasLocalQualifiers);
+ REGISTER_MATCHER(hasLoopInit);
+ REGISTER_MATCHER(hasMethod);
+ REGISTER_MATCHER(hasName);
+ REGISTER_MATCHER(hasObjectExpression);
+ REGISTER_MATCHER(hasOperatorName);
+ REGISTER_MATCHER(hasOverloadedOperatorName);
+ REGISTER_MATCHER(hasParameter);
+ REGISTER_MATCHER(hasParent);
+ REGISTER_MATCHER(hasQualifier);
+ REGISTER_MATCHER(hasRHS);
+ REGISTER_MATCHER(hasSingleDecl);
+ REGISTER_MATCHER(hasSize);
+ REGISTER_MATCHER(hasSizeExpr);
+ REGISTER_MATCHER(hasSourceExpression);
+ REGISTER_MATCHER(hasTargetDecl);
+ REGISTER_MATCHER(hasTemplateArgument);
+ REGISTER_MATCHER(hasTrueExpression);
+ REGISTER_MATCHER(hasUnaryOperand);
+ REGISTER_MATCHER(hasValueType);
+ REGISTER_MATCHER(ifStmt);
+ REGISTER_MATCHER(ignoringImpCasts);
+ REGISTER_MATCHER(ignoringParenCasts);
+ REGISTER_MATCHER(ignoringParenImpCasts);
+ REGISTER_MATCHER(implicitCastExpr);
+ REGISTER_MATCHER(incompleteArrayType);
+ REGISTER_MATCHER(initListExpr);
+ REGISTER_MATCHER(innerType);
+ REGISTER_MATCHER(integerLiteral);
+ REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isConstQualified);
+ REGISTER_MATCHER(isDefinition);
+ REGISTER_MATCHER(isExplicitTemplateSpecialization);
+ REGISTER_MATCHER(isExternC);
+ REGISTER_MATCHER(isImplicit);
+ REGISTER_MATCHER(isInteger);
+ REGISTER_MATCHER(isOverride);
+ REGISTER_MATCHER(isPrivate);
+ REGISTER_MATCHER(isProtected);
+ REGISTER_MATCHER(isPublic);
+ REGISTER_MATCHER(isTemplateInstantiation);
+ REGISTER_MATCHER(isVirtual);
+ REGISTER_MATCHER(isWritten);
+ REGISTER_MATCHER(lValueReferenceType);
+ REGISTER_MATCHER(labelStmt);
+ REGISTER_MATCHER(lambdaExpr);
+ REGISTER_MATCHER(matchesName);
+ REGISTER_MATCHER(materializeTemporaryExpr);
+ REGISTER_MATCHER(member);
+ REGISTER_MATCHER(memberCallExpr);
+ REGISTER_MATCHER(memberExpr);
+ REGISTER_MATCHER(memberPointerType);
+ REGISTER_MATCHER(methodDecl);
+ REGISTER_MATCHER(namedDecl);
+ REGISTER_MATCHER(namesType);
+ REGISTER_MATCHER(namespaceDecl);
+ REGISTER_MATCHER(nestedNameSpecifier);
+ REGISTER_MATCHER(nestedNameSpecifierLoc);
+ REGISTER_MATCHER(newExpr);
+ REGISTER_MATCHER(nullPtrLiteralExpr);
+ REGISTER_MATCHER(nullStmt);
+ REGISTER_MATCHER(ofClass);
+ REGISTER_MATCHER(on);
+ REGISTER_MATCHER(onImplicitObjectArgument);
+ REGISTER_MATCHER(operatorCallExpr);
+ REGISTER_MATCHER(parameterCountIs);
+ REGISTER_MATCHER(parenType);
+ REGISTER_MATCHER(pointee);
+ REGISTER_MATCHER(pointerType);
+ REGISTER_MATCHER(qualType);
+ REGISTER_MATCHER(rValueReferenceType);
+ REGISTER_MATCHER(recordDecl);
+ REGISTER_MATCHER(recordType);
+ REGISTER_MATCHER(referenceType);
+ REGISTER_MATCHER(refersToDeclaration);
+ REGISTER_MATCHER(refersToType);
+ REGISTER_MATCHER(reinterpretCastExpr);
+ REGISTER_MATCHER(returnStmt);
+ REGISTER_MATCHER(returns);
+ REGISTER_MATCHER(sizeOfExpr);
+ REGISTER_MATCHER(specifiesNamespace);
+ REGISTER_MATCHER(specifiesType);
+ REGISTER_MATCHER(specifiesTypeLoc);
+ REGISTER_MATCHER(statementCountIs);
+ REGISTER_MATCHER(staticCastExpr);
+ REGISTER_MATCHER(stmt);
+ REGISTER_MATCHER(stringLiteral);
+ REGISTER_MATCHER(switchCase);
+ REGISTER_MATCHER(switchStmt);
+ REGISTER_MATCHER(templateSpecializationType);
+ REGISTER_MATCHER(thisExpr);
+ REGISTER_MATCHER(throughUsingDecl);
+ REGISTER_MATCHER(throwExpr);
+ REGISTER_MATCHER(to);
+ REGISTER_MATCHER(tryStmt);
+ REGISTER_MATCHER(type);
+ REGISTER_MATCHER(typeLoc);
+ REGISTER_MATCHER(typedefType);
+ REGISTER_MATCHER(unaryExprOrTypeTraitExpr);
+ REGISTER_MATCHER(unaryOperator);
+ REGISTER_MATCHER(userDefinedLiteral);
+ REGISTER_MATCHER(usingDecl);
+ REGISTER_MATCHER(varDecl);
+ REGISTER_MATCHER(variableArrayType);
+ REGISTER_MATCHER(whileStmt);
+ REGISTER_MATCHER(withInitializer);
+}
+
+RegistryMaps::~RegistryMaps() {
+ for (ConstructorMap::iterator it = Constructors.begin(),
+ end = Constructors.end();
+ it != end; ++it) {
+ delete it->second;
+ }
+}
+
+static llvm::ManagedStatic<RegistryMaps> RegistryData;
+
+} // anonymous namespace
+
+// static
+VariantMatcher Registry::constructMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ ConstructorMap::const_iterator it =
+ RegistryData->constructors().find(MatcherName);
+ if (it == RegistryData->constructors().end()) {
+ Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName;
+ return VariantMatcher();
+ }
+
+ return it->second->run(NameRange, Args, Error);
+}
+
+// static
+VariantMatcher Registry::constructBoundMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ VariantMatcher Out = constructMatcher(MatcherName, NameRange, Args, Error);
+ if (Out.isNull()) return Out;
+
+ llvm::Optional<DynTypedMatcher> Result = Out.getSingleMatcher();
+ if (Result.hasValue()) {
+ llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
+ if (Bound.hasValue()) {
+ return VariantMatcher::SingleMatcher(*Bound);
+ }
+ }
+ Error->addError(NameRange, Error->ET_RegistryNotBindable);
+ return VariantMatcher();
+}
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
new file mode 100644
index 0000000..3e49e1b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -0,0 +1,256 @@
+//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Polymorphic value type.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+VariantMatcher::MatcherOps::~MatcherOps() {}
+VariantMatcher::Payload::~Payload() {}
+
+class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
+public:
+ SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
+
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
+ return Matcher;
+ }
+
+ virtual std::string getTypeAsString() const {
+ return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
+ .str();
+ }
+
+ virtual void makeTypedMatcher(MatcherOps &Ops) const {
+ if (Ops.canConstructFrom(Matcher))
+ Ops.constructFrom(Matcher);
+ }
+
+private:
+ const DynTypedMatcher Matcher;
+};
+
+class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
+public:
+ PolymorphicPayload(ArrayRef<DynTypedMatcher> MatchersIn)
+ : Matchers(MatchersIn) {}
+
+ virtual ~PolymorphicPayload() {}
+
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
+ if (Matchers.size() != 1)
+ return llvm::Optional<DynTypedMatcher>();
+ return Matchers[0];
+ }
+
+ virtual std::string getTypeAsString() const {
+ std::string Inner;
+ for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
+ if (i != 0)
+ Inner += "|";
+ Inner += Matchers[i].getSupportedKind().asStringRef();
+ }
+ return (Twine("Matcher<") + Inner + ">").str();
+ }
+
+ virtual void makeTypedMatcher(MatcherOps &Ops) const {
+ const DynTypedMatcher *Found = NULL;
+ for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
+ if (Ops.canConstructFrom(Matchers[i])) {
+ if (Found)
+ return;
+ Found = &Matchers[i];
+ }
+ }
+ if (Found)
+ Ops.constructFrom(*Found);
+ }
+
+ const std::vector<DynTypedMatcher> Matchers;
+};
+
+class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
+public:
+ VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> Args)
+ : Func(Func), Args(Args) {}
+
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
+ return llvm::Optional<DynTypedMatcher>();
+ }
+
+ virtual std::string getTypeAsString() const {
+ std::string Inner;
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ if (i != 0)
+ Inner += "&";
+ Inner += Args[i].getTypeAsString();
+ }
+ return Inner;
+ }
+
+ virtual void makeTypedMatcher(MatcherOps &Ops) const {
+ Ops.constructVariadicOperator(Func, Args);
+ }
+
+private:
+ const ast_matchers::internal::VariadicOperatorFunction Func;
+ const std::vector<VariantMatcher> Args;
+};
+
+VariantMatcher::VariantMatcher() {}
+
+VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
+ return VariantMatcher(new SinglePayload(Matcher));
+}
+
+VariantMatcher
+VariantMatcher::PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers) {
+ return VariantMatcher(new PolymorphicPayload(Matchers));
+}
+
+VariantMatcher VariantMatcher::VariadicOperatorMatcher(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> Args) {
+ return VariantMatcher(new VariadicOpPayload(Func, Args));
+}
+
+llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
+ return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
+}
+
+void VariantMatcher::reset() { Value.reset(); }
+
+std::string VariantMatcher::getTypeAsString() const {
+ if (Value) return Value->getTypeAsString();
+ return "<Nothing>";
+}
+
+VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
+ *this = Other;
+}
+
+VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
+ setUnsigned(Unsigned);
+}
+
+VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
+ setString(String);
+}
+
+VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
+ setMatcher(Matcher);
+}
+
+VariantValue::~VariantValue() { reset(); }
+
+VariantValue &VariantValue::operator=(const VariantValue &Other) {
+ if (this == &Other) return *this;
+ reset();
+ switch (Other.Type) {
+ case VT_Unsigned:
+ setUnsigned(Other.getUnsigned());
+ break;
+ case VT_String:
+ setString(Other.getString());
+ break;
+ case VT_Matcher:
+ setMatcher(Other.getMatcher());
+ break;
+ case VT_Nothing:
+ Type = VT_Nothing;
+ break;
+ }
+ return *this;
+}
+
+void VariantValue::reset() {
+ switch (Type) {
+ case VT_String:
+ delete Value.String;
+ break;
+ case VT_Matcher:
+ delete Value.Matcher;
+ break;
+ // Cases that do nothing.
+ case VT_Unsigned:
+ case VT_Nothing:
+ break;
+ }
+ Type = VT_Nothing;
+}
+
+bool VariantValue::isUnsigned() const {
+ return Type == VT_Unsigned;
+}
+
+unsigned VariantValue::getUnsigned() const {
+ assert(isUnsigned());
+ return Value.Unsigned;
+}
+
+void VariantValue::setUnsigned(unsigned NewValue) {
+ reset();
+ Type = VT_Unsigned;
+ Value.Unsigned = NewValue;
+}
+
+bool VariantValue::isString() const {
+ return Type == VT_String;
+}
+
+const std::string &VariantValue::getString() const {
+ assert(isString());
+ return *Value.String;
+}
+
+void VariantValue::setString(const std::string &NewValue) {
+ reset();
+ Type = VT_String;
+ Value.String = new std::string(NewValue);
+}
+
+bool VariantValue::isMatcher() const {
+ return Type == VT_Matcher;
+}
+
+const VariantMatcher &VariantValue::getMatcher() const {
+ assert(isMatcher());
+ return *Value.Matcher;
+}
+
+void VariantValue::setMatcher(const VariantMatcher &NewValue) {
+ reset();
+ Type = VT_Matcher;
+ Value.Matcher = new VariantMatcher(NewValue);
+}
+
+std::string VariantValue::getTypeAsString() const {
+ switch (Type) {
+ case VT_String: return "String";
+ case VT_Matcher: return getMatcher().getTypeAsString();
+ case VT_Unsigned: return "Unsigned";
+ case VT_Nothing: return "Nothing";
+ }
+ llvm_unreachable("Invalid Type");
+}
+
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
OpenPOWER on IntegriCloud