1//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
2//                     The LLVM Compiler Infrastructure
3//
4// This file is distributed under the University of Illinois Open Source
5// License. See LICENSE.TXT for details.
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// \brief Polymorphic value type.
11///
12/// Supports all the types required for dynamic Matcher construction.
13///  Used by the registry to construct matchers in a generic way.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
18#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
19
20#include <vector>
21
22#include "clang/ASTMatchers/ASTMatchers.h"
23#include "clang/ASTMatchers/ASTMatchersInternal.h"
24#include "llvm/ADT/Twine.h"
25#include "llvm/Support/type_traits.h"
26
27namespace clang {
28namespace ast_matchers {
29namespace dynamic {
30
31using ast_matchers::internal::DynTypedMatcher;
32
33/// \brief A list of \c DynTypedMatcher objects.
34///
35/// The purpose of this list is to wrap multiple different matchers and
36/// provide the right one when calling \c hasTypedMatcher/getTypedMatcher.
37class MatcherList {
38public:
39  /// \brief An empty list.
40  MatcherList();
41  /// \brief Clones the matcher objects.
42  MatcherList(const MatcherList &Other);
43  /// \brief Clones the provided matcher.
44  MatcherList(const DynTypedMatcher &Matcher);
45  ~MatcherList();
46
47  MatcherList &operator=(const MatcherList &Other);
48
49  /// \brief Add a matcher to this list. The matcher is cloned.
50  void add(const DynTypedMatcher &Matcher);
51
52  /// \brief Empties the list.
53  void reset();
54
55  /// \brief Whether the list is empty.
56  bool empty() const { return List.empty(); }
57
58  ArrayRef<const DynTypedMatcher *> matchers() const { return List; }
59
60  /// \brief Determines if any of the contained matchers can be converted
61  ///   to \c Matcher<T>.
62  ///
63  /// Returns true if one, and only one, of the contained matchers can be
64  /// converted to \c Matcher<T>. If there are more than one that can, the
65  /// result would be ambigous and false is returned.
66  template <class T>
67  bool hasTypedMatcher() const {
68    size_t Matches = 0;
69    for (size_t I = 0, E = List.size(); I != E; ++I) {
70      Matches += ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]);
71    }
72    return Matches == 1;
73  }
74
75  /// \brief Wrap the correct matcher as a \c Matcher<T>.
76  ///
77  /// Selects the appropriate matcher from the list and returns it as a
78  /// \c Matcher<T>.
79  /// Asserts that \c hasTypedMatcher<T>() is true.
80  template <class T>
81  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
82    assert(hasTypedMatcher<T>());
83    for (size_t I = 0, E = List.size(); I != E; ++I) {
84      if (ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]))
85        return ast_matchers::internal::Matcher<T>::constructFrom(*List[I]);
86    }
87    llvm_unreachable("!hasTypedMatcher<T>()");
88  }
89
90  /// \brief String representation of the type of the value.
91  ///
92  /// If there are more than one matcher on the list, the string will show all
93  /// the types.
94  std::string getTypeAsString() const;
95
96private:
97  std::vector<const DynTypedMatcher *> List;
98};
99
100/// \brief Variant value class.
101///
102/// Basically, a tagged union with value type semantics.
103/// It is used by the registry as the return value and argument type for the
104/// matcher factory methods.
105/// It can be constructed from any of the supported types. It supports
106/// copy/assignment.
107///
108/// Supported types:
109///  - \c unsigned
110///  - \c std::string
111///  - \c MatcherList (\c DynTypedMatcher / \c Matcher<T>)
112class VariantValue {
113public:
114  VariantValue() : Type(VT_Nothing) {}
115
116  VariantValue(const VariantValue &Other);
117  ~VariantValue();
118  VariantValue &operator=(const VariantValue &Other);
119
120  /// \brief Specific constructors for each supported type.
121  VariantValue(unsigned Unsigned);
122  VariantValue(const std::string &String);
123  VariantValue(const DynTypedMatcher &Matcher);
124  VariantValue(const MatcherList &Matchers);
125
126  /// \brief Unsigned value functions.
127  bool isUnsigned() const;
128  unsigned getUnsigned() const;
129  void setUnsigned(unsigned Unsigned);
130
131  /// \brief String value functions.
132  bool isString() const;
133  const std::string &getString() const;
134  void setString(const std::string &String);
135
136  /// \brief Matcher value functions.
137  bool isMatchers() const;
138  const MatcherList &getMatchers() const;
139  void setMatchers(const MatcherList &Matchers);
140
141  /// \brief Shortcut functions.
142  template <class T>
143  bool hasTypedMatcher() const {
144    return isMatchers() && getMatchers().hasTypedMatcher<T>();
145  }
146
147  template <class T>
148  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
149    return getMatchers().getTypedMatcher<T>();
150  }
151
152  /// \brief String representation of the type of the value.
153  std::string getTypeAsString() const;
154
155private:
156  void reset();
157
158  /// \brief All supported value types.
159  enum ValueType {
160    VT_Nothing,
161    VT_Unsigned,
162    VT_String,
163    VT_Matchers
164  };
165
166  /// \brief All supported value types.
167  union AllValues {
168    unsigned Unsigned;
169    std::string *String;
170    MatcherList *Matchers;
171  };
172
173  ValueType Type;
174  AllValues Value;
175};
176
177} // end namespace dynamic
178} // end namespace ast_matchers
179} // end namespace clang
180
181#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
182