1480093f4SDimitry Andric//==--- PropertiesBase.td - Baseline definitions for AST properties -------===//
2480093f4SDimitry Andric//
3480093f4SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric//
7480093f4SDimitry Andric//===----------------------------------------------------------------------===//
8480093f4SDimitry Andric
9480093f4SDimitry Andricclass HasProperties;
10480093f4SDimitry Andric
11480093f4SDimitry Andric/// The type of the property.
12480093f4SDimitry Andricclass PropertyType<string typeName = ""> {
13480093f4SDimitry Andric  /// The C++ type name for the type.
14480093f4SDimitry Andric  string CXXName = !if(!ne(typeName, ""), typeName, NAME);
15480093f4SDimitry Andric
16480093f4SDimitry Andric  /// Whether the C++ type should generally be passed around by reference.
17480093f4SDimitry Andric  bit PassByReference = 0;
18480093f4SDimitry Andric
19480093f4SDimitry Andric  /// Whether `const` should be prepended to the type when writing.
20480093f4SDimitry Andric  bit ConstWhenWriting = 0;
21480093f4SDimitry Andric
22480093f4SDimitry Andric  /// Given a value of type Optional<CXXName> bound as 'value', yield a
23480093f4SDimitry Andric  /// CXXName that can be serialized into a DataStreamTypeWriter.
24480093f4SDimitry Andric  string PackOptional = "";
25480093f4SDimitry Andric
26480093f4SDimitry Andric  /// Given a value of type CXXName bound as 'value' that was deserialized
27480093f4SDimitry Andric  /// by a DataStreamTypeReader, yield an Optional<CXXName>.
28480093f4SDimitry Andric  string UnpackOptional = "";
29480093f4SDimitry Andric
30480093f4SDimitry Andric  /// A list of types for which buffeers must be passed to the read
31480093f4SDimitry Andric  /// operations.
32480093f4SDimitry Andric  list<PropertyType> BufferElementTypes = [];
33480093f4SDimitry Andric}
34480093f4SDimitry Andric
35480093f4SDimitry Andric/// Property types that correspond to specific C++ enums.
36480093f4SDimitry Andricclass EnumPropertyType<string typeName = ""> : PropertyType<typeName> {}
37480093f4SDimitry Andric
38480093f4SDimitry Andric/// Property types that correspond to a specific C++ class.
39480093f4SDimitry Andric/// Supports optional values by using the null representation.
40480093f4SDimitry Andricclass RefPropertyType<string className> : PropertyType<className # "*"> {
41480093f4SDimitry Andric  let PackOptional =
42480093f4SDimitry Andric    "value ? *value : nullptr";
43480093f4SDimitry Andric  let UnpackOptional =
44bdd1243dSDimitry Andric    "value ? std::optional<" # CXXName # ">(value) : std::nullopt";
45480093f4SDimitry Andric}
46480093f4SDimitry Andric
47480093f4SDimitry Andric/// Property types that correspond to a specific subclass of another type.
48480093f4SDimitry Andricclass SubclassPropertyType<string className, PropertyType base>
49480093f4SDimitry Andric    : RefPropertyType<className> {
50480093f4SDimitry Andric  PropertyType Base = base;
51480093f4SDimitry Andric  string SubclassName = className;
52480093f4SDimitry Andric  let ConstWhenWriting = base.ConstWhenWriting;
53480093f4SDimitry Andric}
54480093f4SDimitry Andric
55480093f4SDimitry Andric/// Property types that support optional values by using their
56480093f4SDimitry Andric/// default value.
57480093f4SDimitry Andricclass DefaultValuePropertyType<string typeName = ""> : PropertyType<typeName> {
58480093f4SDimitry Andric  let PackOptional =
59480093f4SDimitry Andric    "value ? *value : " # CXXName # "()";
60480093f4SDimitry Andric  let UnpackOptional =
61bdd1243dSDimitry Andric    "value.isNull() ? std::nullopt : std::optional<" # CXXName # ">(value)";
62480093f4SDimitry Andric}
63480093f4SDimitry Andric
64480093f4SDimitry Andric/// Property types that correspond to integer types and support optional
65480093f4SDimitry Andric/// values by shifting the value over by 1.
66480093f4SDimitry Andricclass CountPropertyType<string typeName = ""> : PropertyType<typeName> {
67480093f4SDimitry Andric  let PackOptional =
68480093f4SDimitry Andric    "value ? *value + 1 : 0";
69480093f4SDimitry Andric  let UnpackOptional =
70bdd1243dSDimitry Andric    "value ? std::optional<" # CXXName # ">(value - 1) : std::nullopt";
71480093f4SDimitry Andric}
72480093f4SDimitry Andric
73480093f4SDimitry Andricdef APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
74480093f4SDimitry Andricdef APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
75e8d8bef9SDimitry Andricdef APValue : PropertyType { let PassByReference = 1; }
76e8d8bef9SDimitry Andricdef APValueKind : EnumPropertyType<"APValue::ValueKind">;
775f757f3fSDimitry Andricdef ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">;
78480093f4SDimitry Andricdef AttrKind : EnumPropertyType<"attr::Kind">;
79480093f4SDimitry Andricdef AutoTypeKeyword : EnumPropertyType;
80480093f4SDimitry Andricdef Bool : PropertyType<"bool">;
81480093f4SDimitry Andricdef BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
8281ad6265SDimitry Andricdef BTFTypeTagAttr : PropertyType<"const BTFTypeTagAttr *">;
83480093f4SDimitry Andricdef CallingConv : EnumPropertyType;
84480093f4SDimitry Andricdef DeclarationName : PropertyType;
85480093f4SDimitry Andricdef DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">;
86480093f4SDimitry Andricdef DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; }
87480093f4SDimitry Andric  def CXXRecordDeclRef :
88480093f4SDimitry Andric    SubclassPropertyType<"CXXRecordDecl", DeclRef>;
89480093f4SDimitry Andric  def FunctionDeclRef :
90480093f4SDimitry Andric    SubclassPropertyType<"FunctionDecl", DeclRef>;
91480093f4SDimitry Andric  def NamedDeclRef :
92480093f4SDimitry Andric    SubclassPropertyType<"NamedDecl", DeclRef>;
93480093f4SDimitry Andric  def NamespaceDeclRef :
94480093f4SDimitry Andric    SubclassPropertyType<"NamespaceDecl", DeclRef>;
95480093f4SDimitry Andric  def NamespaceAliasDeclRef :
96480093f4SDimitry Andric    SubclassPropertyType<"NamespaceAliasDecl", DeclRef>;
97480093f4SDimitry Andric  def ObjCProtocolDeclRef :
98480093f4SDimitry Andric    SubclassPropertyType<"ObjCProtocolDecl", DeclRef>;
99480093f4SDimitry Andric  def ObjCTypeParamDeclRef :
100480093f4SDimitry Andric    SubclassPropertyType<"ObjCTypeParamDecl", DeclRef>;
101480093f4SDimitry Andric  def TagDeclRef :
102480093f4SDimitry Andric    SubclassPropertyType<"TagDecl", DeclRef>;
103480093f4SDimitry Andric  def TemplateDeclRef :
104480093f4SDimitry Andric    SubclassPropertyType<"TemplateDecl", DeclRef>;
10555e4f9d5SDimitry Andric  def ConceptDeclRef :
10655e4f9d5SDimitry Andric    SubclassPropertyType<"ConceptDecl", DeclRef>;
107480093f4SDimitry Andric  def TemplateTypeParmDeclRef :
108480093f4SDimitry Andric    SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>;
109480093f4SDimitry Andric  def TemplateTemplateParmDeclRef :
110480093f4SDimitry Andric    SubclassPropertyType<"TemplateTemplateParmDecl", DeclRef>;
1110eae32dcSDimitry Andric  def UsingShadowDeclRef :
1120eae32dcSDimitry Andric    SubclassPropertyType<"UsingShadowDecl", DeclRef>;
113480093f4SDimitry Andric  def ValueDeclRef :
114480093f4SDimitry Andric    SubclassPropertyType<"ValueDecl", DeclRef>;
115480093f4SDimitry Andricdef ElaboratedTypeKeyword : EnumPropertyType;
116480093f4SDimitry Andricdef ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
117e8d8bef9SDimitry Andricdef FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> {
118e8d8bef9SDimitry Andric  let PassByReference = 1;
119e8d8bef9SDimitry Andric}
120480093f4SDimitry Andricdef Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
121e8d8bef9SDimitry Andricdef LValuePathEntry : PropertyType<"APValue::LValuePathEntry">;
122e8d8bef9SDimitry Andricdef LValuePathSerializationHelper :
123e8d8bef9SDimitry Andric    PropertyType<"APValue::LValuePathSerializationHelper"> {
124e8d8bef9SDimitry Andric  let BufferElementTypes = [ LValuePathEntry ];
125e8d8bef9SDimitry Andric}
126480093f4SDimitry Andricdef NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
127480093f4SDimitry Andricdef NestedNameSpecifierKind :
128480093f4SDimitry Andric  EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
129480093f4SDimitry Andricdef OverloadedOperatorKind : EnumPropertyType;
130480093f4SDimitry Andricdef Qualifiers : PropertyType;
131480093f4SDimitry Andricdef QualType : DefaultValuePropertyType;
132480093f4SDimitry Andricdef RefQualifierKind : EnumPropertyType;
133480093f4SDimitry Andricdef Selector : PropertyType;
134480093f4SDimitry Andricdef SourceLocation : PropertyType;
135480093f4SDimitry Andricdef StmtRef : RefPropertyType<"Stmt"> { let ConstWhenWriting = 1; }
136480093f4SDimitry Andric  def ExprRef : SubclassPropertyType<"Expr", StmtRef>;
137480093f4SDimitry Andricdef TemplateArgument : PropertyType;
138480093f4SDimitry Andricdef TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
139480093f4SDimitry Andricdef TemplateName : DefaultValuePropertyType;
140480093f4SDimitry Andricdef TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
141bdd1243dSDimitry Andricdef TypeOfKind : EnumPropertyType<"TypeOfKind">;
142480093f4SDimitry Andricdef UInt32 : CountPropertyType<"uint32_t">;
143480093f4SDimitry Andricdef UInt64 : CountPropertyType<"uint64_t">;
144480093f4SDimitry Andricdef UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
1455f757f3fSDimitry Andricdef VectorKind : EnumPropertyType<"VectorKind">;
146480093f4SDimitry Andric
147480093f4SDimitry Andricdef ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> {
148480093f4SDimitry Andric  let BufferElementTypes = [ QualType ];
149480093f4SDimitry Andric}
150480093f4SDimitry Andric
151480093f4SDimitry Andric/// Arrays.  The corresponding C++ type is ArrayRef of the corresponding
152480093f4SDimitry Andric/// C++ type of the element.
153480093f4SDimitry Andricclass Array<PropertyType element> : PropertyType {
154480093f4SDimitry Andric  PropertyType Element = element;
155480093f4SDimitry Andric  let BufferElementTypes = [ element ];
156480093f4SDimitry Andric}
157480093f4SDimitry Andric
158bdd1243dSDimitry Andric/// std::optional<T>.  The corresponding C++ type is generally just the
159480093f4SDimitry Andric/// corresponding C++ type of the element.
160480093f4SDimitry Andric///
161480093f4SDimitry Andric/// Optional<Unsigned> may restrict the range of the operand for some
162480093f4SDimitry Andric/// serialization clients.
163480093f4SDimitry Andricclass Optional<PropertyType element> : PropertyType {
164480093f4SDimitry Andric  PropertyType Element = element;
165480093f4SDimitry Andric  let PassByReference = element.PassByReference;
166480093f4SDimitry Andric}
167480093f4SDimitry Andric
168480093f4SDimitry Andric/// A property of an AST node.
169480093f4SDimitry Andricclass Property<string name, PropertyType type> {
170480093f4SDimitry Andric  HasProperties Class;
171480093f4SDimitry Andric  string Name = name;
172480093f4SDimitry Andric  PropertyType Type = type;
173480093f4SDimitry Andric
174480093f4SDimitry Andric  /// A function for reading the property, expressed in terms of a variable
175480093f4SDimitry Andric  /// "node".
176480093f4SDimitry Andric  code Read;
177480093f4SDimitry Andric
178480093f4SDimitry Andric  /// Code specifying when this property is available.  Can be defined
179480093f4SDimitry Andric  /// in terms of other properties, in which case this property must be
180480093f4SDimitry Andric  /// read/written after those properties.  Using this will make the
181480093f4SDimitry Andric  /// value Optional when deserializing.
182480093f4SDimitry Andric  ///
183480093f4SDimitry Andric  /// FIXME: the emitter doesn't yet force dependent properties to be
184480093f4SDimitry Andric  /// read/written later; this only works if the properties used in the
185480093f4SDimitry Andric  /// condition happen to be written first.
186480093f4SDimitry Andric  code Conditional = "";
187480093f4SDimitry Andric}
188480093f4SDimitry Andric
189480093f4SDimitry Andric/// A rule for declaring helper variables when read properties from a
190480093f4SDimitry Andric/// value of this type.  Note that this means that this code is actually
191480093f4SDimitry Andric/// run when *writing* values of this type; however, naming this
192480093f4SDimitry Andric/// `ReadHelper` makes the connection to the `Read` operations on the
193480093f4SDimitry Andric/// properties much clearer.
194480093f4SDimitry Andricclass ReadHelper<code _code> {
195480093f4SDimitry Andric  HasProperties Class;
196480093f4SDimitry Andric
197480093f4SDimitry Andric  /// Code which will be run when writing objects of this type before
198480093f4SDimitry Andric  /// writing any of the properties, specified in terms of a variable
199480093f4SDimitry Andric  /// `node`.
200480093f4SDimitry Andric  code Code = _code;
201480093f4SDimitry Andric}
202480093f4SDimitry Andric
203480093f4SDimitry Andric/// A rule for creating objects of this type.
204480093f4SDimitry Andricclass Creator<code create> {
205480093f4SDimitry Andric  HasProperties Class;
206480093f4SDimitry Andric
207480093f4SDimitry Andric  /// A function for creating values of this kind, expressed in terms of a
208480093f4SDimitry Andric  /// variable `ctx` of type `ASTContext &`.  Must also refer to all of the
209480093f4SDimitry Andric  /// properties by name.
210480093f4SDimitry Andric  code Create = create;
211480093f4SDimitry Andric}
212480093f4SDimitry Andric
213480093f4SDimitry Andric/// A rule which overrides some of the normal rules.
214480093f4SDimitry Andricclass Override {
215480093f4SDimitry Andric  HasProperties Class;
216480093f4SDimitry Andric
217480093f4SDimitry Andric  /// Properties from base classes that should be ignored.
218480093f4SDimitry Andric  list<string> IgnoredProperties = [];
219480093f4SDimitry Andric}
220480093f4SDimitry Andric
221480093f4SDimitry Andric/// A description of how to break a type into cases.  Providing this and
222480093f4SDimitry Andric/// an exhaustive list of the cases will cause AbstractBasic{Reader,Writer}
223480093f4SDimitry Andric/// to be generated with a default implementation of how to read the
224480093f4SDimitry Andric/// type.
225480093f4SDimitry Andric///
226480093f4SDimitry Andric/// Creator rules for the cases can additionally access a variable
227480093f4SDimitry Andric/// `kind` of the KindType.
228480093f4SDimitry Andricclass PropertyTypeKind<PropertyType type,
229480093f4SDimitry Andric                       PropertyType kindType,
230480093f4SDimitry Andric                       string readCode> {
231480093f4SDimitry Andric  /// The type for which this describes cases.
232480093f4SDimitry Andric  PropertyType Type = type;
233480093f4SDimitry Andric
234480093f4SDimitry Andric  /// The type of this type's kind enum.
235480093f4SDimitry Andric  PropertyType KindType = kindType;
236480093f4SDimitry Andric
237480093f4SDimitry Andric  /// The property name to use for the kind.
238480093f4SDimitry Andric  string KindPropertyName = "kind";
239480093f4SDimitry Andric
240480093f4SDimitry Andric  /// An expression which reads the kind from a value, expressed in terms
241480093f4SDimitry Andric  /// of a variable `node`.
242480093f4SDimitry Andric  string Read = readCode;
243480093f4SDimitry Andric}
244480093f4SDimitry Andric
245480093f4SDimitry Andric/// One of the options for representing a particular type.
246480093f4SDimitry Andricclass PropertyTypeCase<PropertyType type, string name> : HasProperties {
247480093f4SDimitry Andric  /// The type of which this is a case.
248480093f4SDimitry Andric  PropertyType Type = type;
249480093f4SDimitry Andric
250480093f4SDimitry Andric  /// The name of the case (a value of the type's kind enum).
251480093f4SDimitry Andric  string Name = name;
252480093f4SDimitry Andric}
253480093f4SDimitry Andric
254e8d8bef9SDimitry Andric// Type cases for APValue.
255e8d8bef9SDimitry Andricdef : PropertyTypeKind<APValue, APValueKind,
256e8d8bef9SDimitry Andric                       "node.getKind()">;
257e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "None"> in {
258e8d8bef9SDimitry Andric  def : Creator<[{ return APValue(); }]>;
259e8d8bef9SDimitry Andric}
260e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Indeterminate"> in {
261e8d8bef9SDimitry Andric  def : Creator<[{ return APValue::IndeterminateValue(); }]>;
262e8d8bef9SDimitry Andric}
263e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Int"> in {
264e8d8bef9SDimitry Andric  def : Property<"value", APSInt> {
265e8d8bef9SDimitry Andric    let Read = [{ node.getInt() }];
266e8d8bef9SDimitry Andric  }
267e8d8bef9SDimitry Andric  def : Creator<[{ return APValue(value); }]>;
268e8d8bef9SDimitry Andric}
269e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Float"> in {
270e8d8bef9SDimitry Andric  def : Property<"semantics", UInt32> {
271e8d8bef9SDimitry Andric    let Read = [{
272e8d8bef9SDimitry Andric      static_cast<uint32_t>(
273e8d8bef9SDimitry Andric        llvm::APFloatBase::SemanticsToEnum(node.getFloat().getSemantics()))
274e8d8bef9SDimitry Andric    }];
275e8d8bef9SDimitry Andric  }
276e8d8bef9SDimitry Andric  def : Property<"value", APInt> {
277e8d8bef9SDimitry Andric    let Read = [{ node.getFloat().bitcastToAPInt() }];
278e8d8bef9SDimitry Andric  }
279e8d8bef9SDimitry Andric  def : Creator<[{
280e8d8bef9SDimitry Andric    const llvm::fltSemantics &floatSema = llvm::APFloatBase::EnumToSemantics(
281e8d8bef9SDimitry Andric        static_cast<llvm::APFloatBase::Semantics>(semantics));
282e8d8bef9SDimitry Andric    return APValue(llvm::APFloat(floatSema, value));
283e8d8bef9SDimitry Andric  }]>;
284e8d8bef9SDimitry Andric}
285e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "FixedPoint"> in {
286e8d8bef9SDimitry Andric  def : Property<"semantics", FixedPointSemantics> {
287e8d8bef9SDimitry Andric    let Read = [{ node.getFixedPoint().getSemantics() }];
288e8d8bef9SDimitry Andric  }
289e8d8bef9SDimitry Andric  def : Property<"value", APSInt> {
290e8d8bef9SDimitry Andric    let Read = [{ node.getFixedPoint().getValue() }];
291e8d8bef9SDimitry Andric  }
292e8d8bef9SDimitry Andric  def : Creator<[{
293e8d8bef9SDimitry Andric    return APValue(llvm::APFixedPoint(std::move(value), semantics));
294e8d8bef9SDimitry Andric  }]>;
295e8d8bef9SDimitry Andric}
296e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "ComplexInt"> in {
297e8d8bef9SDimitry Andric  def : Property<"real", APSInt> {
298e8d8bef9SDimitry Andric    let Read = [{ node.getComplexIntReal() }];
299e8d8bef9SDimitry Andric  }
300e8d8bef9SDimitry Andric  def : Property<"imag", APSInt> {
301e8d8bef9SDimitry Andric    let Read = [{ node.getComplexIntImag() }];
302e8d8bef9SDimitry Andric  }
303e8d8bef9SDimitry Andric  def : Creator<[{ return APValue(real, imag); }]>;
304e8d8bef9SDimitry Andric}
305e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "ComplexFloat"> in {
306e8d8bef9SDimitry Andric  def : ReadHelper<[{
307e8d8bef9SDimitry Andric    auto sema = llvm::APFloatBase::SemanticsToEnum(
308e8d8bef9SDimitry Andric        node.getComplexFloatReal().getSemantics());
309e8d8bef9SDimitry Andric    assert(sema == llvm::APFloatBase::SemanticsToEnum(
310e8d8bef9SDimitry Andric        node.getComplexFloatImag().getSemantics()));
311e8d8bef9SDimitry Andric  }]>;
312e8d8bef9SDimitry Andric  def : Property<"semantics", UInt32> {
313e8d8bef9SDimitry Andric    let Read = [{ static_cast<uint32_t>(sema) }];
314e8d8bef9SDimitry Andric  }
315e8d8bef9SDimitry Andric  def : Property<"real", APInt> {
316e8d8bef9SDimitry Andric    let Read = [{ node.getComplexFloatReal().bitcastToAPInt() }];
317e8d8bef9SDimitry Andric  }
318e8d8bef9SDimitry Andric  def : Property<"imag", APInt> {
319e8d8bef9SDimitry Andric    let Read = [{ node.getComplexFloatImag().bitcastToAPInt() }];
320e8d8bef9SDimitry Andric  }
321e8d8bef9SDimitry Andric  def : Creator<[{
322e8d8bef9SDimitry Andric    const llvm::fltSemantics &sema = llvm::APFloatBase::EnumToSemantics(
323e8d8bef9SDimitry Andric        static_cast<llvm::APFloatBase::Semantics>(semantics));
324e8d8bef9SDimitry Andric    return APValue(llvm::APFloat(sema, real),
325e8d8bef9SDimitry Andric                   llvm::APFloat(sema, imag));
326e8d8bef9SDimitry Andric  }]>;
327e8d8bef9SDimitry Andric}
328e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Vector"> in {
329e8d8bef9SDimitry Andric  def : ReadHelper<[{
330e8d8bef9SDimitry Andric    SmallVector<APValue, 4> buffer;
331e8d8bef9SDimitry Andric    unsigned len = node.getVectorLength();
332e8d8bef9SDimitry Andric    for (unsigned i = 0; i < len; ++i)
333e8d8bef9SDimitry Andric      buffer.push_back(node.getVectorElt(i));
334e8d8bef9SDimitry Andric  }]>;
335e8d8bef9SDimitry Andric  def : Property<"elements", Array<APValue>> {
336e8d8bef9SDimitry Andric    let Read = [{ buffer }];
337e8d8bef9SDimitry Andric  }
338e8d8bef9SDimitry Andric  def : Creator<[{
339e8d8bef9SDimitry Andric    APValue result;
340e8d8bef9SDimitry Andric    result.MakeVector();
341e8d8bef9SDimitry Andric    unsigned length = elements.size();
342e8d8bef9SDimitry Andric    (void)result.setVectorUninit(length);
343e8d8bef9SDimitry Andric    for (unsigned i = 0; i < length; i++)
344e8d8bef9SDimitry Andric      result.getVectorElt(i) = elements[i];
345e8d8bef9SDimitry Andric    return result;
346e8d8bef9SDimitry Andric  }]>;
347e8d8bef9SDimitry Andric}
348e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Array"> in {
349e8d8bef9SDimitry Andric  def : ReadHelper<[{
350e8d8bef9SDimitry Andric    SmallVector<APValue, 4> buffer{};
351e8d8bef9SDimitry Andric    unsigned initLength = node.getArrayInitializedElts();
352e8d8bef9SDimitry Andric    for (unsigned i = 0; i < initLength; ++i)
353e8d8bef9SDimitry Andric      buffer.push_back(node.getArrayInitializedElt(i));
354e8d8bef9SDimitry Andric    if (node.hasArrayFiller())
355e8d8bef9SDimitry Andric      buffer.push_back(node.getArrayFiller());
356e8d8bef9SDimitry Andric  }]>;
357e8d8bef9SDimitry Andric  def : Property<"totalLength", UInt32> {
358e8d8bef9SDimitry Andric    let Read = [{ node.getArraySize() }];
359e8d8bef9SDimitry Andric  }
360e8d8bef9SDimitry Andric  def : Property<"hasFiller", Bool> {
361e8d8bef9SDimitry Andric    let Read = [{ node.hasArrayFiller() }];
362e8d8bef9SDimitry Andric  }
363e8d8bef9SDimitry Andric  def : Property<"elements", Array<APValue>> {
364e8d8bef9SDimitry Andric    let Read = [{ buffer }];
365e8d8bef9SDimitry Andric  }
366e8d8bef9SDimitry Andric  def : Creator<[{
367e8d8bef9SDimitry Andric    APValue result;
368e8d8bef9SDimitry Andric    unsigned initLength = elements.size() - (hasFiller ? 1 : 0);
369e8d8bef9SDimitry Andric    result.MakeArray(initLength, totalLength);
370e8d8bef9SDimitry Andric    for (unsigned i = 0; i < initLength; ++i)
371e8d8bef9SDimitry Andric      result.getArrayInitializedElt(i) = elements[i];
372e8d8bef9SDimitry Andric    if (hasFiller)
373e8d8bef9SDimitry Andric      result.getArrayFiller() = elements.back();
374e8d8bef9SDimitry Andric    return result;
375e8d8bef9SDimitry Andric  }]>;
376e8d8bef9SDimitry Andric}
377e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Struct"> in {
378e8d8bef9SDimitry Andric  def : ReadHelper<[{
379e8d8bef9SDimitry Andric    SmallVector<APValue, 4> structBases;
380e8d8bef9SDimitry Andric    unsigned numBases = node.getStructNumBases();
381e8d8bef9SDimitry Andric    for (unsigned i = 0; i < numBases; ++i)
382e8d8bef9SDimitry Andric      structBases.push_back(node.getStructBase(i));
383e8d8bef9SDimitry Andric    SmallVector<APValue, 4> structFields;
384e8d8bef9SDimitry Andric    unsigned numFields = node.getStructNumFields();
385e8d8bef9SDimitry Andric    for (unsigned i = 0; i < numFields; ++i)
386e8d8bef9SDimitry Andric      structFields.push_back(node.getStructField(i));
387e8d8bef9SDimitry Andric  }]>;
388e8d8bef9SDimitry Andric  def : Property<"bases", Array<APValue>> {
389e8d8bef9SDimitry Andric    let Read = [{ structBases }];
390e8d8bef9SDimitry Andric  }
391e8d8bef9SDimitry Andric  def : Property<"fields", Array<APValue>> {
392e8d8bef9SDimitry Andric    let Read = [{ structFields }];
393e8d8bef9SDimitry Andric  }
394e8d8bef9SDimitry Andric  def : Creator<[{
395e8d8bef9SDimitry Andric    APValue result;
396e8d8bef9SDimitry Andric    result.MakeStruct(bases.size(), fields.size());
397e8d8bef9SDimitry Andric    for (unsigned i = 0; i < bases.size(); ++i)
398e8d8bef9SDimitry Andric      result.getStructBase(i) = bases[i];
399e8d8bef9SDimitry Andric    for (unsigned i = 0; i < fields.size(); ++i)
400e8d8bef9SDimitry Andric      result.getStructField(i) = fields[i];
401e8d8bef9SDimitry Andric    return result;
402e8d8bef9SDimitry Andric  }]>;
403e8d8bef9SDimitry Andric}
404e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "Union"> in {
405e8d8bef9SDimitry Andric  def : Property<"fieldDecl", DeclRef> {
406e8d8bef9SDimitry Andric    let Read = [{ node.getUnionField() }];
407e8d8bef9SDimitry Andric  }
408e8d8bef9SDimitry Andric  def : Property<"value", APValue> {
409e8d8bef9SDimitry Andric    let Read = [{ node.getUnionValue() }];
410e8d8bef9SDimitry Andric  }
411e8d8bef9SDimitry Andric  def : Creator<[{
412e8d8bef9SDimitry Andric    return APValue(cast<clang::FieldDecl>(fieldDecl), std::move(value));
413e8d8bef9SDimitry Andric  }]>;
414e8d8bef9SDimitry Andric}
415e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "AddrLabelDiff"> in {
416e8d8bef9SDimitry Andric  def : Property<"lhs", StmtRef> {
417e8d8bef9SDimitry Andric    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffLHS()) }];
418e8d8bef9SDimitry Andric  }
419e8d8bef9SDimitry Andric  def : Property<"rhs", StmtRef> {
420e8d8bef9SDimitry Andric    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffRHS()) }];
421e8d8bef9SDimitry Andric  }
422e8d8bef9SDimitry Andric  def : Creator<[{
423e8d8bef9SDimitry Andric    return APValue(cast<AddrLabelExpr>(lhs), cast<AddrLabelExpr>(rhs));
424e8d8bef9SDimitry Andric  }]>;
425e8d8bef9SDimitry Andric}
426e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "MemberPointer"> in {
427e8d8bef9SDimitry Andric  def : Property<"isDerived", Bool> {
428e8d8bef9SDimitry Andric    let Read = [{ node.isMemberPointerToDerivedMember() }];
429e8d8bef9SDimitry Andric  }
430e8d8bef9SDimitry Andric  def : Property<"member", ValueDeclRef> {
431e8d8bef9SDimitry Andric    let Read = [{ node.getMemberPointerDecl() }];
432e8d8bef9SDimitry Andric  }
433e8d8bef9SDimitry Andric  def : Property<"memberPath", Array<CXXRecordDeclRef>> {
434e8d8bef9SDimitry Andric    let Read = [{ node.getMemberPointerPath() }];
435e8d8bef9SDimitry Andric  }
436e8d8bef9SDimitry Andric  def : Creator<[{
437e8d8bef9SDimitry Andric    APValue result;
438e8d8bef9SDimitry Andric    unsigned pathSize = memberPath.size();
439e8d8bef9SDimitry Andric    const CXXRecordDecl **pathArray =
440e8d8bef9SDimitry Andric        result.setMemberPointerUninit(member, isDerived, pathSize).data();
441e8d8bef9SDimitry Andric    for (unsigned i = 0; i < pathSize; ++i)
442e8d8bef9SDimitry Andric      pathArray[i] = memberPath[i]->getCanonicalDecl();
443e8d8bef9SDimitry Andric    return result;
444e8d8bef9SDimitry Andric  }]>;
445e8d8bef9SDimitry Andric}
446e8d8bef9SDimitry Andriclet Class = PropertyTypeCase<APValue, "LValue"> in {
447e8d8bef9SDimitry Andric  def : ReadHelper<[{
448e8d8bef9SDimitry Andric    auto lvalueBase = node.getLValueBase();
449e8d8bef9SDimitry Andric    const Expr *expr =
450e8d8bef9SDimitry Andric        lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr;
451e8d8bef9SDimitry Andric    bool lvalueBaseIsExpr = (bool) expr;
452e8d8bef9SDimitry Andric    bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>();
45306c3fb27SDimitry Andric    bool lvalueBaseIsDynamicAlloc = lvalueBase.is<DynamicAllocLValue>();
454e8d8bef9SDimitry Andric    QualType elemTy;
455e8d8bef9SDimitry Andric    if (lvalueBase) {
456e8d8bef9SDimitry Andric      if (lvalueBaseIsTypeInfo) {
457e8d8bef9SDimitry Andric        elemTy = lvalueBase.getTypeInfoType();
45806c3fb27SDimitry Andric      } else if (lvalueBaseIsDynamicAlloc) {
45906c3fb27SDimitry Andric        elemTy = lvalueBase.getDynamicAllocType();
460e8d8bef9SDimitry Andric      } else if (lvalueBaseIsExpr) {
461e8d8bef9SDimitry Andric        elemTy = expr->getType();
462e8d8bef9SDimitry Andric      } else {
463e8d8bef9SDimitry Andric        elemTy = lvalueBase.get<const ValueDecl *>()->getType();
464e8d8bef9SDimitry Andric      }
465e8d8bef9SDimitry Andric    }
466e8d8bef9SDimitry Andric  }]>;
467e8d8bef9SDimitry Andric  def : Property<"hasLValuePath", Bool> {
468e8d8bef9SDimitry Andric    let Read = [{ node.hasLValuePath() }];
469e8d8bef9SDimitry Andric  }
470e8d8bef9SDimitry Andric  def : Property<"isLValueOnePastTheEnd", Bool> {
471e8d8bef9SDimitry Andric    let Read = [{ node.isLValueOnePastTheEnd() }];
472e8d8bef9SDimitry Andric  }
473e8d8bef9SDimitry Andric  def : Property<"isExpr", Bool> {
474e8d8bef9SDimitry Andric    let Read = [{ lvalueBaseIsExpr }];
475e8d8bef9SDimitry Andric  }
476e8d8bef9SDimitry Andric  def : Property<"isTypeInfo", Bool> {
477e8d8bef9SDimitry Andric    let Read = [{ lvalueBaseIsTypeInfo }];
478e8d8bef9SDimitry Andric  }
47906c3fb27SDimitry Andric  def : Property<"isDynamicAlloc", Bool> {
48006c3fb27SDimitry Andric    let Read = [{ lvalueBaseIsDynamicAlloc }];
48106c3fb27SDimitry Andric  }
482e8d8bef9SDimitry Andric  def : Property<"hasBase", Bool> {
483e8d8bef9SDimitry Andric    let Read = [{ static_cast<bool>(lvalueBase) }];
484e8d8bef9SDimitry Andric  }
485e8d8bef9SDimitry Andric  def : Property<"isNullPtr", Bool> {
486e8d8bef9SDimitry Andric    let Read = [{ node.isNullPointer() }];
487e8d8bef9SDimitry Andric  }
488e8d8bef9SDimitry Andric  def : Property<"typeInfo", QualType> {
489e8d8bef9SDimitry Andric    let Conditional = [{ hasBase && isTypeInfo }];
490e8d8bef9SDimitry Andric    let Read = [{
491e8d8bef9SDimitry Andric      QualType(node.getLValueBase().get<TypeInfoLValue>().getType(), 0)
492e8d8bef9SDimitry Andric    }];
493e8d8bef9SDimitry Andric  }
49406c3fb27SDimitry Andric  def : Property<"dynamicAlloc", UInt32> {
49506c3fb27SDimitry Andric    let Conditional = [{ hasBase && isDynamicAlloc }];
49606c3fb27SDimitry Andric    let Read = [{ node.getLValueBase().get<DynamicAllocLValue>().getIndex() }];
49706c3fb27SDimitry Andric  }
498e8d8bef9SDimitry Andric  def : Property<"type", QualType> {
49906c3fb27SDimitry Andric    let Conditional = [{ hasBase && (isTypeInfo || isDynamicAlloc) }];
50006c3fb27SDimitry Andric    let Read = [{
50106c3fb27SDimitry Andric      isTypeInfo
50206c3fb27SDimitry Andric        ? node.getLValueBase().getTypeInfoType()
50306c3fb27SDimitry Andric        : node.getLValueBase().getDynamicAllocType()
50406c3fb27SDimitry Andric    }];
505e8d8bef9SDimitry Andric  }
506e8d8bef9SDimitry Andric  def : Property<"callIndex", UInt32> {
507e8d8bef9SDimitry Andric    let Conditional = [{ hasBase && !isTypeInfo }];
508e8d8bef9SDimitry Andric    let Read = [{ node.getLValueBase().getCallIndex() }];
509e8d8bef9SDimitry Andric  }
510e8d8bef9SDimitry Andric  def : Property<"version", UInt32> {
511e8d8bef9SDimitry Andric    let Conditional = [{ hasBase && !isTypeInfo }];
512e8d8bef9SDimitry Andric    let Read = [{ node.getLValueBase().getVersion() }];
513e8d8bef9SDimitry Andric  }
514e8d8bef9SDimitry Andric  def : Property<"stmt", StmtRef> {
515e8d8bef9SDimitry Andric    let Conditional = [{ hasBase && !isTypeInfo && isExpr }];
516e8d8bef9SDimitry Andric    let Read = [{ const_cast<Expr *>(expr) }];
517e8d8bef9SDimitry Andric  }
518e8d8bef9SDimitry Andric  def : Property<"decl", DeclRef> {
51906c3fb27SDimitry Andric    let Conditional = [{ hasBase && !isTypeInfo && !isDynamicAlloc && !isExpr }];
520e8d8bef9SDimitry Andric    let Read = [{ lvalueBase.get<const ValueDecl *>() }];
521e8d8bef9SDimitry Andric  }
522e8d8bef9SDimitry Andric  def : Property<"offsetQuantity", UInt32> {
523e8d8bef9SDimitry Andric    let Read = [{ node.getLValueOffset().getQuantity() }];
524e8d8bef9SDimitry Andric  }
525e8d8bef9SDimitry Andric  def : Property<"lvaluePath", LValuePathSerializationHelper> {
526e8d8bef9SDimitry Andric    let Conditional = [{ hasLValuePath }];
527e8d8bef9SDimitry Andric    let Read = [{
528e8d8bef9SDimitry Andric      APValue::LValuePathSerializationHelper(node.getLValuePath(), elemTy)
529e8d8bef9SDimitry Andric    }];
530e8d8bef9SDimitry Andric  }
531e8d8bef9SDimitry Andric  def : Creator<[{
532e8d8bef9SDimitry Andric    (void)ctx;
533e8d8bef9SDimitry Andric    APValue::LValueBase base;
534e8d8bef9SDimitry Andric    if (hasBase) {
535e8d8bef9SDimitry Andric      if (isTypeInfo) {
536e8d8bef9SDimitry Andric        base = APValue::LValueBase::getTypeInfo(
537bdd1243dSDimitry Andric            TypeInfoLValue(typeInfo->getTypePtr()), *type);
53806c3fb27SDimitry Andric      } else if (isDynamicAlloc) {
53906c3fb27SDimitry Andric        base = APValue::LValueBase::getDynamicAlloc(
54006c3fb27SDimitry Andric            DynamicAllocLValue(*dynamicAlloc), *type);
541e8d8bef9SDimitry Andric      } else if (isExpr) {
542bdd1243dSDimitry Andric        base = APValue::LValueBase(cast<Expr>(*stmt),
543bdd1243dSDimitry Andric                                   *callIndex, *version);
544e8d8bef9SDimitry Andric      } else {
545bdd1243dSDimitry Andric        base = APValue::LValueBase(cast<ValueDecl>(*decl),
546bdd1243dSDimitry Andric                                   *callIndex, *version);
547e8d8bef9SDimitry Andric      }
548e8d8bef9SDimitry Andric    }
549e8d8bef9SDimitry Andric    CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
550e8d8bef9SDimitry Andric    APValue result;
551e8d8bef9SDimitry Andric    result.MakeLValue();
552e8d8bef9SDimitry Andric    if (!hasLValuePath) {
553e8d8bef9SDimitry Andric      result.setLValue(base, offset, APValue::NoLValuePath{}, isNullPtr);
554e8d8bef9SDimitry Andric      return result;
555e8d8bef9SDimitry Andric    }
556e8d8bef9SDimitry Andric    auto pathLength = lvaluePath->Path.size();
557e8d8bef9SDimitry Andric    APValue::LValuePathEntry *path = result.setLValueUninit(
558e8d8bef9SDimitry Andric        base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
559e8d8bef9SDimitry Andric    llvm::copy(lvaluePath->Path, path);
560e8d8bef9SDimitry Andric    return result;
561e8d8bef9SDimitry Andric  }]>;
562e8d8bef9SDimitry Andric}
563e8d8bef9SDimitry Andric
564480093f4SDimitry Andric// Type cases for DeclarationName.
565480093f4SDimitry Andricdef : PropertyTypeKind<DeclarationName, DeclarationNameKind,
566480093f4SDimitry Andric                       "node.getNameKind()">;
567480093f4SDimitry Andriclet Class = PropertyTypeCase<DeclarationName, "Identifier"> in {
568480093f4SDimitry Andric  def : Property<"identifier", Identifier> {
569480093f4SDimitry Andric    let Read = [{ node.getAsIdentifierInfo() }];
570480093f4SDimitry Andric  }
571480093f4SDimitry Andric  def : Creator<[{
572480093f4SDimitry Andric    return DeclarationName(identifier);
573480093f4SDimitry Andric  }]>;
574480093f4SDimitry Andric}
575480093f4SDimitry Andricforeach count = ["Zero", "One", "Multi"] in {
576480093f4SDimitry Andric  let Class = PropertyTypeCase<DeclarationName, "ObjC"#count#"ArgSelector"> in {
577480093f4SDimitry Andric    def : Property<"selector", Selector> {
578480093f4SDimitry Andric      let Read = [{ node.getObjCSelector() }];
579480093f4SDimitry Andric    }
580480093f4SDimitry Andric    def : Creator<[{
581480093f4SDimitry Andric      return DeclarationName(selector);
582480093f4SDimitry Andric    }]>;
583480093f4SDimitry Andric  }
584480093f4SDimitry Andric}
585480093f4SDimitry Andricforeach kind = ["Constructor", "Destructor", "ConversionFunction"] in {
586480093f4SDimitry Andric  let Class = PropertyTypeCase<DeclarationName, "CXX"#kind#"Name"> in {
587480093f4SDimitry Andric    def : Property<"type", QualType> {
588480093f4SDimitry Andric      let Read = [{ node.getCXXNameType() }];
589480093f4SDimitry Andric    }
590480093f4SDimitry Andric    def : Creator<[{
591480093f4SDimitry Andric      return ctx.DeclarationNames.getCXX}]#kind#[{Name(
592480093f4SDimitry Andric               ctx.getCanonicalType(type));
593480093f4SDimitry Andric    }]>;
594480093f4SDimitry Andric  }
595480093f4SDimitry Andric}
596480093f4SDimitry Andriclet Class = PropertyTypeCase<DeclarationName, "CXXDeductionGuideName"> in {
597480093f4SDimitry Andric  def : Property<"declaration", TemplateDeclRef> {
598480093f4SDimitry Andric    let Read = [{ node.getCXXDeductionGuideTemplate() }];
599480093f4SDimitry Andric  }
600480093f4SDimitry Andric  def : Creator<[{
601480093f4SDimitry Andric    return ctx.DeclarationNames.getCXXDeductionGuideName(declaration);
602480093f4SDimitry Andric  }]>;
603480093f4SDimitry Andric}
604480093f4SDimitry Andriclet Class = PropertyTypeCase<DeclarationName, "CXXOperatorName"> in {
605480093f4SDimitry Andric  def : Property<"operatorKind", OverloadedOperatorKind> {
606480093f4SDimitry Andric    let Read = [{ node.getCXXOverloadedOperator() }];
607480093f4SDimitry Andric  }
608480093f4SDimitry Andric  def : Creator<[{
609480093f4SDimitry Andric    return ctx.DeclarationNames.getCXXOperatorName(operatorKind);
610480093f4SDimitry Andric  }]>;
611480093f4SDimitry Andric}
612480093f4SDimitry Andriclet Class = PropertyTypeCase<DeclarationName, "CXXLiteralOperatorName"> in {
613480093f4SDimitry Andric  def : Property<"identifier", Identifier> {
614480093f4SDimitry Andric    let Read = [{ node.getCXXLiteralIdentifier() }];
615480093f4SDimitry Andric  }
616480093f4SDimitry Andric  def : Creator<[{
617480093f4SDimitry Andric    return ctx.DeclarationNames.getCXXLiteralOperatorName(identifier);
618480093f4SDimitry Andric  }]>;
619480093f4SDimitry Andric}
620480093f4SDimitry Andriclet Class = PropertyTypeCase<DeclarationName, "CXXUsingDirective"> in {
621480093f4SDimitry Andric  def : Creator<[{
622480093f4SDimitry Andric    return DeclarationName::getUsingDirectiveName();
623480093f4SDimitry Andric  }]>;
624480093f4SDimitry Andric}
625480093f4SDimitry Andric
626480093f4SDimitry Andric// Type cases for TemplateName.
627480093f4SDimitry Andricdef : PropertyTypeKind<TemplateName, TemplateNameKind, "node.getKind()">;
628480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "Template"> in {
629480093f4SDimitry Andric  def : Property<"declaration", TemplateDeclRef> {
630480093f4SDimitry Andric    let Read = [{ node.getAsTemplateDecl() }];
631480093f4SDimitry Andric  }
632480093f4SDimitry Andric  def : Creator<[{
633480093f4SDimitry Andric    return TemplateName(declaration);
634480093f4SDimitry Andric  }]>;
635480093f4SDimitry Andric}
63681ad6265SDimitry Andric
63781ad6265SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "UsingTemplate"> in {
63881ad6265SDimitry Andric  def : Property<"foundDecl", UsingShadowDeclRef> {
63981ad6265SDimitry Andric    let Read = [{ node.getAsUsingShadowDecl() }];
64081ad6265SDimitry Andric  }
64181ad6265SDimitry Andric  def : Creator<[{
64281ad6265SDimitry Andric    return TemplateName(foundDecl);
64381ad6265SDimitry Andric  }]>;
64481ad6265SDimitry Andric}
64581ad6265SDimitry Andric
646480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in {
647480093f4SDimitry Andric  def : Property<"overloads", Array<NamedDeclRef>> {
648480093f4SDimitry Andric    let Read = [{ node.getAsOverloadedTemplate()->decls() }];
649480093f4SDimitry Andric  }
650480093f4SDimitry Andric  def : Creator<[{
651480093f4SDimitry Andric    // Copy into an UnresolvedSet to satisfy the interface.
652480093f4SDimitry Andric    UnresolvedSet<8> overloadSet;
653480093f4SDimitry Andric    for (auto overload : overloads) {
654480093f4SDimitry Andric      overloadSet.addDecl(overload);
655480093f4SDimitry Andric    }
656480093f4SDimitry Andric
657480093f4SDimitry Andric    return ctx.getOverloadedTemplateName(overloadSet.begin(),
658480093f4SDimitry Andric                                         overloadSet.end());
659480093f4SDimitry Andric  }]>;
660480093f4SDimitry Andric}
661480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "AssumedTemplate"> in {
662480093f4SDimitry Andric  def : Property<"name", DeclarationName> {
663480093f4SDimitry Andric    let Read = [{ node.getAsAssumedTemplateName()->getDeclName() }];
664480093f4SDimitry Andric  }
665480093f4SDimitry Andric  def : Creator<[{
666480093f4SDimitry Andric    return ctx.getAssumedTemplateName(name);
667480093f4SDimitry Andric  }]>;
668480093f4SDimitry Andric}
669480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
670480093f4SDimitry Andric  def : ReadHelper<[{
671480093f4SDimitry Andric    auto qtn = node.getAsQualifiedTemplateName();
672480093f4SDimitry Andric  }]>;
673480093f4SDimitry Andric  def : Property<"qualifier", NestedNameSpecifier> {
674480093f4SDimitry Andric    let Read = [{ qtn->getQualifier() }];
675480093f4SDimitry Andric  }
676480093f4SDimitry Andric  def : Property<"hasTemplateKeyword", Bool> {
677480093f4SDimitry Andric    let Read = [{ qtn->hasTemplateKeyword() }];
678480093f4SDimitry Andric  }
67981ad6265SDimitry Andric  def : Property<"underlyingTemplateName", TemplateName> {
68081ad6265SDimitry Andric    let Read = [{ qtn->getUnderlyingTemplate() }];
681480093f4SDimitry Andric  }
682480093f4SDimitry Andric  def : Creator<[{
683480093f4SDimitry Andric    return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
68481ad6265SDimitry Andric                                        underlyingTemplateName);
685480093f4SDimitry Andric  }]>;
686480093f4SDimitry Andric}
687480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
688480093f4SDimitry Andric  def : ReadHelper<[{
689480093f4SDimitry Andric    auto dtn = node.getAsDependentTemplateName();
690480093f4SDimitry Andric  }]>;
691480093f4SDimitry Andric  def : Property<"qualifier", NestedNameSpecifier> {
692480093f4SDimitry Andric    let Read = [{ dtn->getQualifier() }];
693480093f4SDimitry Andric  }
694480093f4SDimitry Andric  def : Property<"identifier", Optional<Identifier>> {
695480093f4SDimitry Andric    let Read = [{ makeOptionalFromPointer(
696480093f4SDimitry Andric                    dtn->isIdentifier()
697480093f4SDimitry Andric                      ? dtn->getIdentifier()
698480093f4SDimitry Andric                      : nullptr) }];
699480093f4SDimitry Andric  }
700480093f4SDimitry Andric  def : Property<"operatorKind", OverloadedOperatorKind> {
701480093f4SDimitry Andric    let Conditional = [{ !identifier }];
702480093f4SDimitry Andric    let Read = [{ dtn->getOperator() }];
703480093f4SDimitry Andric  }
704480093f4SDimitry Andric  def : Creator<[{
705480093f4SDimitry Andric    if (identifier) {
706480093f4SDimitry Andric      return ctx.getDependentTemplateName(qualifier, *identifier);
707480093f4SDimitry Andric    } else {
708480093f4SDimitry Andric      return ctx.getDependentTemplateName(qualifier, *operatorKind);
709480093f4SDimitry Andric    }
710480093f4SDimitry Andric  }]>;
711480093f4SDimitry Andric}
712480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
713480093f4SDimitry Andric  def : ReadHelper<[{
714480093f4SDimitry Andric    auto parm = node.getAsSubstTemplateTemplateParm();
715480093f4SDimitry Andric  }]>;
716480093f4SDimitry Andric  def : Property<"replacement", TemplateName> {
717480093f4SDimitry Andric    let Read = [{ parm->getReplacement() }];
718480093f4SDimitry Andric  }
719bdd1243dSDimitry Andric  def : Property<"associatedDecl", DeclRef> {
720bdd1243dSDimitry Andric    let Read = [{ parm->getAssociatedDecl() }];
721bdd1243dSDimitry Andric  }
722bdd1243dSDimitry Andric  def : Property<"index", UInt32> {
723bdd1243dSDimitry Andric    let Read = [{ parm->getIndex() }];
724bdd1243dSDimitry Andric  }
725bdd1243dSDimitry Andric  def : Property<"packIndex", Optional<UInt32>> {
726bdd1243dSDimitry Andric    let Read = [{ parm->getPackIndex() }];
727bdd1243dSDimitry Andric  }
728480093f4SDimitry Andric  def : Creator<[{
729bdd1243dSDimitry Andric    return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
730480093f4SDimitry Andric  }]>;
731480093f4SDimitry Andric}
732480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
733480093f4SDimitry Andric  def : ReadHelper<[{
734480093f4SDimitry Andric    auto parm = node.getAsSubstTemplateTemplateParmPack();
735480093f4SDimitry Andric  }]>;
736480093f4SDimitry Andric  def : Property<"argumentPack", TemplateArgument> {
737480093f4SDimitry Andric    let Read = [{ parm->getArgumentPack() }];
738480093f4SDimitry Andric  }
739bdd1243dSDimitry Andric  def : Property<"associatedDecl", DeclRef> {
740bdd1243dSDimitry Andric    let Read = [{ parm->getAssociatedDecl() }];
741bdd1243dSDimitry Andric  }
742bdd1243dSDimitry Andric  def : Property<"index", UInt32> {
743bdd1243dSDimitry Andric    let Read = [{ parm->getIndex() }];
744bdd1243dSDimitry Andric  }
745bdd1243dSDimitry Andric  def : Property<"final", Bool> {
746bdd1243dSDimitry Andric    let Read = [{ parm->getFinal() }];
747bdd1243dSDimitry Andric  }
748480093f4SDimitry Andric  def : Creator<[{
749bdd1243dSDimitry Andric    return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index, final);
750480093f4SDimitry Andric  }]>;
751480093f4SDimitry Andric}
752480093f4SDimitry Andric
753480093f4SDimitry Andric// Type cases for TemplateArgument.
754480093f4SDimitry Andricdef : PropertyTypeKind<TemplateArgument, TemplateArgumentKind,
755480093f4SDimitry Andric                       "node.getKind()">;
756480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Null"> in {
757480093f4SDimitry Andric  def : Creator<[{
758480093f4SDimitry Andric    return TemplateArgument();
759480093f4SDimitry Andric  }]>;
760480093f4SDimitry Andric}
761480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Type"> in {
762480093f4SDimitry Andric  def : Property<"type", QualType> {
763480093f4SDimitry Andric    let Read = [{ node.getAsType() }];
764480093f4SDimitry Andric  }
76506c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
76606c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
76706c3fb27SDimitry Andric  }
768480093f4SDimitry Andric  def : Creator<[{
76906c3fb27SDimitry Andric    return TemplateArgument(type, /* isNullPtr */ false, isDefaulted);
770480093f4SDimitry Andric  }]>;
771480093f4SDimitry Andric}
772480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Declaration"> in {
773480093f4SDimitry Andric  def : Property<"declaration", ValueDeclRef> {
774480093f4SDimitry Andric    let Read = [{ node.getAsDecl() }];
775480093f4SDimitry Andric  }
776480093f4SDimitry Andric  def : Property<"parameterType", QualType> {
777480093f4SDimitry Andric    let Read = [{ node.getParamTypeForDecl() }];
778480093f4SDimitry Andric  }
77906c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
78006c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
78106c3fb27SDimitry Andric  }
782480093f4SDimitry Andric  def : Creator<[{
78306c3fb27SDimitry Andric    return TemplateArgument(declaration, parameterType, isDefaulted);
784480093f4SDimitry Andric  }]>;
785480093f4SDimitry Andric}
786480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in {
787480093f4SDimitry Andric  def : Property<"type", QualType> {
788480093f4SDimitry Andric    let Read = [{ node.getNullPtrType() }];
789480093f4SDimitry Andric  }
79006c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
79106c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
79206c3fb27SDimitry Andric  }
793480093f4SDimitry Andric  def : Creator<[{
79406c3fb27SDimitry Andric    return TemplateArgument(type, /*nullptr*/ true, isDefaulted);
795480093f4SDimitry Andric  }]>;
796480093f4SDimitry Andric}
797480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
798480093f4SDimitry Andric  def : Property<"value", APSInt> {
799480093f4SDimitry Andric    let Read = [{ node.getAsIntegral() }];
800480093f4SDimitry Andric  }
801480093f4SDimitry Andric  def : Property<"type", QualType> {
802480093f4SDimitry Andric    let Read = [{ node.getIntegralType() }];
803480093f4SDimitry Andric  }
80406c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
80506c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
80606c3fb27SDimitry Andric  }
807480093f4SDimitry Andric  def : Creator<[{
80806c3fb27SDimitry Andric    return TemplateArgument(ctx, value, type, isDefaulted);
809480093f4SDimitry Andric  }]>;
810480093f4SDimitry Andric}
811*7a6dacacSDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in {
812*7a6dacacSDimitry Andric  def : Property<"value", APValue> {
813*7a6dacacSDimitry Andric    let Read = [{ node.getAsStructuralValue() }];
814*7a6dacacSDimitry Andric  }
815*7a6dacacSDimitry Andric  def : Property<"type", QualType> {
816*7a6dacacSDimitry Andric    let Read = [{ node.getStructuralValueType() }];
817*7a6dacacSDimitry Andric  }
818*7a6dacacSDimitry Andric  def : Property<"isDefaulted", Bool> {
819*7a6dacacSDimitry Andric    let Read = [{ node.getIsDefaulted() }];
820*7a6dacacSDimitry Andric  }
821*7a6dacacSDimitry Andric  def : Creator<[{
822*7a6dacacSDimitry Andric    return TemplateArgument(ctx, type, value, isDefaulted);
823*7a6dacacSDimitry Andric  }]>;
824*7a6dacacSDimitry Andric}
825480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Template"> in {
826480093f4SDimitry Andric  def : Property<"name", TemplateName> {
827480093f4SDimitry Andric    let Read = [{ node.getAsTemplateOrTemplatePattern() }];
828480093f4SDimitry Andric  }
82906c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
83006c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
83106c3fb27SDimitry Andric  }
832480093f4SDimitry Andric  def : Creator<[{
83306c3fb27SDimitry Andric    return TemplateArgument(name, isDefaulted);
834480093f4SDimitry Andric  }]>;
835480093f4SDimitry Andric}
836480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in {
837480093f4SDimitry Andric  def : Property<"name", TemplateName> {
838480093f4SDimitry Andric    let Read = [{ node.getAsTemplateOrTemplatePattern() }];
839480093f4SDimitry Andric  }
840480093f4SDimitry Andric  def : Property<"numExpansions", Optional<UInt32>> {
841480093f4SDimitry Andric    let Read = [{
842480093f4SDimitry Andric      // Translate unsigned -> uint32_t just in case.
843bdd1243dSDimitry Andric      llvm::transformOptional(node.getNumTemplateExpansions(),
844480093f4SDimitry Andric                              [](unsigned i) { return uint32_t(i); })
845480093f4SDimitry Andric    }];
846480093f4SDimitry Andric  }
84706c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
84806c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
84906c3fb27SDimitry Andric  }
850480093f4SDimitry Andric  def : Creator<[{
851bdd1243dSDimitry Andric    auto numExpansionsUnsigned = llvm::transformOptional(
852bdd1243dSDimitry Andric        numExpansions, [](uint32_t i) { return unsigned(i); });
853bdd1243dSDimitry Andric
85406c3fb27SDimitry Andric    return TemplateArgument(name, numExpansionsUnsigned, isDefaulted);
855480093f4SDimitry Andric  }]>;
856480093f4SDimitry Andric}
857480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
858480093f4SDimitry Andric  def : Property<"expression", ExprRef> {
859480093f4SDimitry Andric    let Read = [{ node.getAsExpr() }];
860480093f4SDimitry Andric  }
86106c3fb27SDimitry Andric  def : Property<"isDefaulted", Bool> {
86206c3fb27SDimitry Andric    let Read = [{ node.getIsDefaulted() }];
86306c3fb27SDimitry Andric  }
864480093f4SDimitry Andric  def : Creator<[{
86506c3fb27SDimitry Andric    return TemplateArgument(expression, isDefaulted);
866480093f4SDimitry Andric  }]>;
867480093f4SDimitry Andric}
868480093f4SDimitry Andriclet Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
869480093f4SDimitry Andric  def : Property<"elements", Array<TemplateArgument>> {
870480093f4SDimitry Andric    let Read = [{ node.pack_elements() }];
871480093f4SDimitry Andric  }
872480093f4SDimitry Andric  def : Creator<[{
873480093f4SDimitry Andric    // Copy the pack into the ASTContext.
874480093f4SDimitry Andric    TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
875480093f4SDimitry Andric    for (size_t i = 0, e = elements.size(); i != e; ++i)
876480093f4SDimitry Andric      ctxElements[i] = elements[i];
877bdd1243dSDimitry Andric    return TemplateArgument(llvm::ArrayRef(ctxElements, elements.size()));
878480093f4SDimitry Andric  }]>;
879480093f4SDimitry Andric}
880