1//==--- PropertiesBase.td - Baseline definitions for AST properties -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9class HasProperties;
10
11/// The type of the property.
12class PropertyType<string typeName = ""> {
13  /// The C++ type name for the type.
14  string CXXName = !if(!ne(typeName, ""), typeName, NAME);
15
16  /// Whether the C++ type should generally be passed around by reference.
17  bit PassByReference = 0;
18
19  /// Whether `const` should be prepended to the type when writing.
20  bit ConstWhenWriting = 0;
21
22  /// Given a value of type Optional<CXXName> bound as 'value', yield a
23  /// CXXName that can be serialized into a DataStreamTypeWriter.
24  string PackOptional = "";
25
26  /// Given a value of type CXXName bound as 'value' that was deserialized
27  /// by a DataStreamTypeReader, yield an Optional<CXXName>.
28  string UnpackOptional = "";
29
30  /// A list of types for which buffeers must be passed to the read
31  /// operations.
32  list<PropertyType> BufferElementTypes = [];
33}
34
35/// Property types that correspond to specific C++ enums.
36class EnumPropertyType<string typeName = ""> : PropertyType<typeName> {}
37
38/// Property types that correspond to a specific C++ class.
39/// Supports optional values by using the null representation.
40class RefPropertyType<string className> : PropertyType<className # "*"> {
41  let PackOptional =
42    "value ? *value : nullptr";
43  let UnpackOptional =
44    "value ? std::optional<" # CXXName # ">(value) : std::nullopt";
45}
46
47/// Property types that correspond to a specific subclass of another type.
48class SubclassPropertyType<string className, PropertyType base>
49    : RefPropertyType<className> {
50  PropertyType Base = base;
51  string SubclassName = className;
52  let ConstWhenWriting = base.ConstWhenWriting;
53}
54
55/// Property types that support optional values by using their
56/// default value.
57class DefaultValuePropertyType<string typeName = ""> : PropertyType<typeName> {
58  let PackOptional =
59    "value ? *value : " # CXXName # "()";
60  let UnpackOptional =
61    "value.isNull() ? std::nullopt : std::optional<" # CXXName # ">(value)";
62}
63
64/// Property types that correspond to integer types and support optional
65/// values by shifting the value over by 1.
66class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
67  let PackOptional =
68    "value ? *value + 1 : 0";
69  let UnpackOptional =
70    "value ? std::optional<" # CXXName # ">(value - 1) : std::nullopt";
71}
72
73def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
74def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
75def APValue : PropertyType { let PassByReference = 1; }
76def APValueKind : EnumPropertyType<"APValue::ValueKind">;
77def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
78def AttrKind : EnumPropertyType<"attr::Kind">;
79def AutoTypeKeyword : EnumPropertyType;
80def Bool : PropertyType<"bool">;
81def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
82def BTFTypeTagAttr : PropertyType<"const BTFTypeTagAttr *">;
83def CallingConv : EnumPropertyType;
84def DeclarationName : PropertyType;
85def DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">;
86def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; }
87  def CXXRecordDeclRef :
88    SubclassPropertyType<"CXXRecordDecl", DeclRef>;
89  def FunctionDeclRef :
90    SubclassPropertyType<"FunctionDecl", DeclRef>;
91  def NamedDeclRef :
92    SubclassPropertyType<"NamedDecl", DeclRef>;
93  def NamespaceDeclRef :
94    SubclassPropertyType<"NamespaceDecl", DeclRef>;
95  def NamespaceAliasDeclRef :
96    SubclassPropertyType<"NamespaceAliasDecl", DeclRef>;
97  def ObjCProtocolDeclRef :
98    SubclassPropertyType<"ObjCProtocolDecl", DeclRef>;
99  def ObjCTypeParamDeclRef :
100    SubclassPropertyType<"ObjCTypeParamDecl", DeclRef>;
101  def TagDeclRef :
102    SubclassPropertyType<"TagDecl", DeclRef>;
103  def TemplateDeclRef :
104    SubclassPropertyType<"TemplateDecl", DeclRef>;
105  def ConceptDeclRef :
106    SubclassPropertyType<"ConceptDecl", DeclRef>;
107  def TemplateTypeParmDeclRef :
108    SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>;
109  def TemplateTemplateParmDeclRef :
110    SubclassPropertyType<"TemplateTemplateParmDecl", DeclRef>;
111  def UsingShadowDeclRef :
112    SubclassPropertyType<"UsingShadowDecl", DeclRef>;
113  def ValueDeclRef :
114    SubclassPropertyType<"ValueDecl", DeclRef>;
115def ElaboratedTypeKeyword : EnumPropertyType;
116def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
117def FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> {
118  let PassByReference = 1;
119}
120def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
121def LValuePathEntry : PropertyType<"APValue::LValuePathEntry">;
122def LValuePathSerializationHelper :
123    PropertyType<"APValue::LValuePathSerializationHelper"> {
124  let BufferElementTypes = [ LValuePathEntry ];
125}
126def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
127def NestedNameSpecifierKind :
128  EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
129def OverloadedOperatorKind : EnumPropertyType;
130def Qualifiers : PropertyType;
131def QualType : DefaultValuePropertyType;
132def RefQualifierKind : EnumPropertyType;
133def Selector : PropertyType;
134def SourceLocation : PropertyType;
135def StmtRef : RefPropertyType<"Stmt"> { let ConstWhenWriting = 1; }
136  def ExprRef : SubclassPropertyType<"Expr", StmtRef>;
137def TemplateArgument : PropertyType;
138def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
139def TemplateName : DefaultValuePropertyType;
140def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
141def TypeOfKind : EnumPropertyType<"TypeOfKind">;
142def UInt32 : CountPropertyType<"uint32_t">;
143def UInt64 : CountPropertyType<"uint64_t">;
144def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
145def VectorKind : EnumPropertyType<"VectorType::VectorKind">;
146
147def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> {
148  let BufferElementTypes = [ QualType ];
149}
150
151/// Arrays.  The corresponding C++ type is ArrayRef of the corresponding
152/// C++ type of the element.
153class Array<PropertyType element> : PropertyType {
154  PropertyType Element = element;
155  let BufferElementTypes = [ element ];
156}
157
158/// std::optional<T>.  The corresponding C++ type is generally just the
159/// corresponding C++ type of the element.
160///
161/// Optional<Unsigned> may restrict the range of the operand for some
162/// serialization clients.
163class Optional<PropertyType element> : PropertyType {
164  PropertyType Element = element;
165  let PassByReference = element.PassByReference;
166}
167
168/// A property of an AST node.
169class Property<string name, PropertyType type> {
170  HasProperties Class;
171  string Name = name;
172  PropertyType Type = type;
173
174  /// A function for reading the property, expressed in terms of a variable
175  /// "node".
176  code Read;
177
178  /// Code specifying when this property is available.  Can be defined
179  /// in terms of other properties, in which case this property must be
180  /// read/written after those properties.  Using this will make the
181  /// value Optional when deserializing.
182  ///
183  /// FIXME: the emitter doesn't yet force dependent properties to be
184  /// read/written later; this only works if the properties used in the
185  /// condition happen to be written first.
186  code Conditional = "";
187}
188
189/// A rule for declaring helper variables when read properties from a
190/// value of this type.  Note that this means that this code is actually
191/// run when *writing* values of this type; however, naming this
192/// `ReadHelper` makes the connection to the `Read` operations on the
193/// properties much clearer.
194class ReadHelper<code _code> {
195  HasProperties Class;
196
197  /// Code which will be run when writing objects of this type before
198  /// writing any of the properties, specified in terms of a variable
199  /// `node`.
200  code Code = _code;
201}
202
203/// A rule for creating objects of this type.
204class Creator<code create> {
205  HasProperties Class;
206
207  /// A function for creating values of this kind, expressed in terms of a
208  /// variable `ctx` of type `ASTContext &`.  Must also refer to all of the
209  /// properties by name.
210  code Create = create;
211}
212
213/// A rule which overrides some of the normal rules.
214class Override {
215  HasProperties Class;
216
217  /// Properties from base classes that should be ignored.
218  list<string> IgnoredProperties = [];
219}
220
221/// A description of how to break a type into cases.  Providing this and
222/// an exhaustive list of the cases will cause AbstractBasic{Reader,Writer}
223/// to be generated with a default implementation of how to read the
224/// type.
225///
226/// Creator rules for the cases can additionally access a variable
227/// `kind` of the KindType.
228class PropertyTypeKind<PropertyType type,
229                       PropertyType kindType,
230                       string readCode> {
231  /// The type for which this describes cases.
232  PropertyType Type = type;
233
234  /// The type of this type's kind enum.
235  PropertyType KindType = kindType;
236
237  /// The property name to use for the kind.
238  string KindPropertyName = "kind";
239
240  /// An expression which reads the kind from a value, expressed in terms
241  /// of a variable `node`.
242  string Read = readCode;
243}
244
245/// One of the options for representing a particular type.
246class PropertyTypeCase<PropertyType type, string name> : HasProperties {
247  /// The type of which this is a case.
248  PropertyType Type = type;
249
250  /// The name of the case (a value of the type's kind enum).
251  string Name = name;
252}
253
254// Type cases for APValue.
255def : PropertyTypeKind<APValue, APValueKind,
256                       "node.getKind()">;
257let Class = PropertyTypeCase<APValue, "None"> in {
258  def : Creator<[{ return APValue(); }]>;
259}
260let Class = PropertyTypeCase<APValue, "Indeterminate"> in {
261  def : Creator<[{ return APValue::IndeterminateValue(); }]>;
262}
263let Class = PropertyTypeCase<APValue, "Int"> in {
264  def : Property<"value", APSInt> {
265    let Read = [{ node.getInt() }];
266  }
267  def : Creator<[{ return APValue(value); }]>;
268}
269let Class = PropertyTypeCase<APValue, "Float"> in {
270  def : Property<"semantics", UInt32> {
271    let Read = [{
272      static_cast<uint32_t>(
273        llvm::APFloatBase::SemanticsToEnum(node.getFloat().getSemantics()))
274    }];
275  }
276  def : Property<"value", APInt> {
277    let Read = [{ node.getFloat().bitcastToAPInt() }];
278  }
279  def : Creator<[{
280    const llvm::fltSemantics &floatSema = llvm::APFloatBase::EnumToSemantics(
281        static_cast<llvm::APFloatBase::Semantics>(semantics));
282    return APValue(llvm::APFloat(floatSema, value));
283  }]>;
284}
285let Class = PropertyTypeCase<APValue, "FixedPoint"> in {
286  def : Property<"semantics", FixedPointSemantics> {
287    let Read = [{ node.getFixedPoint().getSemantics() }];
288  }
289  def : Property<"value", APSInt> {
290    let Read = [{ node.getFixedPoint().getValue() }];
291  }
292  def : Creator<[{
293    return APValue(llvm::APFixedPoint(std::move(value), semantics));
294  }]>;
295}
296let Class = PropertyTypeCase<APValue, "ComplexInt"> in {
297  def : Property<"real", APSInt> {
298    let Read = [{ node.getComplexIntReal() }];
299  }
300  def : Property<"imag", APSInt> {
301    let Read = [{ node.getComplexIntImag() }];
302  }
303  def : Creator<[{ return APValue(real, imag); }]>;
304}
305let Class = PropertyTypeCase<APValue, "ComplexFloat"> in {
306  def : ReadHelper<[{
307    auto sema = llvm::APFloatBase::SemanticsToEnum(
308        node.getComplexFloatReal().getSemantics());
309    assert(sema == llvm::APFloatBase::SemanticsToEnum(
310        node.getComplexFloatImag().getSemantics()));
311  }]>;
312  def : Property<"semantics", UInt32> {
313    let Read = [{ static_cast<uint32_t>(sema) }];
314  }
315  def : Property<"real", APInt> {
316    let Read = [{ node.getComplexFloatReal().bitcastToAPInt() }];
317  }
318  def : Property<"imag", APInt> {
319    let Read = [{ node.getComplexFloatImag().bitcastToAPInt() }];
320  }
321  def : Creator<[{
322    const llvm::fltSemantics &sema = llvm::APFloatBase::EnumToSemantics(
323        static_cast<llvm::APFloatBase::Semantics>(semantics));
324    return APValue(llvm::APFloat(sema, real),
325                   llvm::APFloat(sema, imag));
326  }]>;
327}
328let Class = PropertyTypeCase<APValue, "Vector"> in {
329  def : ReadHelper<[{
330    SmallVector<APValue, 4> buffer;
331    unsigned len = node.getVectorLength();
332    for (unsigned i = 0; i < len; ++i)
333      buffer.push_back(node.getVectorElt(i));
334  }]>;
335  def : Property<"elements", Array<APValue>> {
336    let Read = [{ buffer }];
337  }
338  def : Creator<[{
339    APValue result;
340    result.MakeVector();
341    unsigned length = elements.size();
342    (void)result.setVectorUninit(length);
343    for (unsigned i = 0; i < length; i++)
344      result.getVectorElt(i) = elements[i];
345    return result;
346  }]>;
347}
348let Class = PropertyTypeCase<APValue, "Array"> in {
349  def : ReadHelper<[{
350    SmallVector<APValue, 4> buffer{};
351    unsigned initLength = node.getArrayInitializedElts();
352    for (unsigned i = 0; i < initLength; ++i)
353      buffer.push_back(node.getArrayInitializedElt(i));
354    if (node.hasArrayFiller())
355      buffer.push_back(node.getArrayFiller());
356  }]>;
357  def : Property<"totalLength", UInt32> {
358    let Read = [{ node.getArraySize() }];
359  }
360  def : Property<"hasFiller", Bool> {
361    let Read = [{ node.hasArrayFiller() }];
362  }
363  def : Property<"elements", Array<APValue>> {
364    let Read = [{ buffer }];
365  }
366  def : Creator<[{
367    APValue result;
368    unsigned initLength = elements.size() - (hasFiller ? 1 : 0);
369    result.MakeArray(initLength, totalLength);
370    for (unsigned i = 0; i < initLength; ++i)
371      result.getArrayInitializedElt(i) = elements[i];
372    if (hasFiller)
373      result.getArrayFiller() = elements.back();
374    return result;
375  }]>;
376}
377let Class = PropertyTypeCase<APValue, "Struct"> in {
378  def : ReadHelper<[{
379    SmallVector<APValue, 4> structBases;
380    unsigned numBases = node.getStructNumBases();
381    for (unsigned i = 0; i < numBases; ++i)
382      structBases.push_back(node.getStructBase(i));
383    SmallVector<APValue, 4> structFields;
384    unsigned numFields = node.getStructNumFields();
385    for (unsigned i = 0; i < numFields; ++i)
386      structFields.push_back(node.getStructField(i));
387  }]>;
388  def : Property<"bases", Array<APValue>> {
389    let Read = [{ structBases }];
390  }
391  def : Property<"fields", Array<APValue>> {
392    let Read = [{ structFields }];
393  }
394  def : Creator<[{
395    APValue result;
396    result.MakeStruct(bases.size(), fields.size());
397    for (unsigned i = 0; i < bases.size(); ++i)
398      result.getStructBase(i) = bases[i];
399    for (unsigned i = 0; i < fields.size(); ++i)
400      result.getStructField(i) = fields[i];
401    return result;
402  }]>;
403}
404let Class = PropertyTypeCase<APValue, "Union"> in {
405  def : Property<"fieldDecl", DeclRef> {
406    let Read = [{ node.getUnionField() }];
407  }
408  def : Property<"value", APValue> {
409    let Read = [{ node.getUnionValue() }];
410  }
411  def : Creator<[{
412    return APValue(cast<clang::FieldDecl>(fieldDecl), std::move(value));
413  }]>;
414}
415let Class = PropertyTypeCase<APValue, "AddrLabelDiff"> in {
416  def : Property<"lhs", StmtRef> {
417    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffLHS()) }];
418  }
419  def : Property<"rhs", StmtRef> {
420    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffRHS()) }];
421  }
422  def : Creator<[{
423    return APValue(cast<AddrLabelExpr>(lhs), cast<AddrLabelExpr>(rhs));
424  }]>;
425}
426let Class = PropertyTypeCase<APValue, "MemberPointer"> in {
427  def : Property<"isDerived", Bool> {
428    let Read = [{ node.isMemberPointerToDerivedMember() }];
429  }
430  def : Property<"member", ValueDeclRef> {
431    let Read = [{ node.getMemberPointerDecl() }];
432  }
433  def : Property<"memberPath", Array<CXXRecordDeclRef>> {
434    let Read = [{ node.getMemberPointerPath() }];
435  }
436  def : Creator<[{
437    APValue result;
438    unsigned pathSize = memberPath.size();
439    const CXXRecordDecl **pathArray =
440        result.setMemberPointerUninit(member, isDerived, pathSize).data();
441    for (unsigned i = 0; i < pathSize; ++i)
442      pathArray[i] = memberPath[i]->getCanonicalDecl();
443    return result;
444  }]>;
445}
446let Class = PropertyTypeCase<APValue, "LValue"> in {
447  def : ReadHelper<[{
448    auto lvalueBase = node.getLValueBase();
449    const Expr *expr =
450        lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr;
451    bool lvalueBaseIsExpr = (bool) expr;
452    bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>();
453    bool lvalueBaseIsDynamicAlloc = lvalueBase.is<DynamicAllocLValue>();
454    QualType elemTy;
455    if (lvalueBase) {
456      if (lvalueBaseIsTypeInfo) {
457        elemTy = lvalueBase.getTypeInfoType();
458      } else if (lvalueBaseIsDynamicAlloc) {
459        elemTy = lvalueBase.getDynamicAllocType();
460      } else if (lvalueBaseIsExpr) {
461        elemTy = expr->getType();
462      } else {
463        elemTy = lvalueBase.get<const ValueDecl *>()->getType();
464      }
465    }
466  }]>;
467  def : Property<"hasLValuePath", Bool> {
468    let Read = [{ node.hasLValuePath() }];
469  }
470  def : Property<"isLValueOnePastTheEnd", Bool> {
471    let Read = [{ node.isLValueOnePastTheEnd() }];
472  }
473  def : Property<"isExpr", Bool> {
474    let Read = [{ lvalueBaseIsExpr }];
475  }
476  def : Property<"isTypeInfo", Bool> {
477    let Read = [{ lvalueBaseIsTypeInfo }];
478  }
479  def : Property<"isDynamicAlloc", Bool> {
480    let Read = [{ lvalueBaseIsDynamicAlloc }];
481  }
482  def : Property<"hasBase", Bool> {
483    let Read = [{ static_cast<bool>(lvalueBase) }];
484  }
485  def : Property<"isNullPtr", Bool> {
486    let Read = [{ node.isNullPointer() }];
487  }
488  def : Property<"typeInfo", QualType> {
489    let Conditional = [{ hasBase && isTypeInfo }];
490    let Read = [{
491      QualType(node.getLValueBase().get<TypeInfoLValue>().getType(), 0)
492    }];
493  }
494  def : Property<"dynamicAlloc", UInt32> {
495    let Conditional = [{ hasBase && isDynamicAlloc }];
496    let Read = [{ node.getLValueBase().get<DynamicAllocLValue>().getIndex() }];
497  }
498  def : Property<"type", QualType> {
499    let Conditional = [{ hasBase && (isTypeInfo || isDynamicAlloc) }];
500    let Read = [{
501      isTypeInfo
502        ? node.getLValueBase().getTypeInfoType()
503        : node.getLValueBase().getDynamicAllocType()
504    }];
505  }
506  def : Property<"callIndex", UInt32> {
507    let Conditional = [{ hasBase && !isTypeInfo }];
508    let Read = [{ node.getLValueBase().getCallIndex() }];
509  }
510  def : Property<"version", UInt32> {
511    let Conditional = [{ hasBase && !isTypeInfo }];
512    let Read = [{ node.getLValueBase().getVersion() }];
513  }
514  def : Property<"stmt", StmtRef> {
515    let Conditional = [{ hasBase && !isTypeInfo && isExpr }];
516    let Read = [{ const_cast<Expr *>(expr) }];
517  }
518  def : Property<"decl", DeclRef> {
519    let Conditional = [{ hasBase && !isTypeInfo && !isDynamicAlloc && !isExpr }];
520    let Read = [{ lvalueBase.get<const ValueDecl *>() }];
521  }
522  def : Property<"offsetQuantity", UInt32> {
523    let Read = [{ node.getLValueOffset().getQuantity() }];
524  }
525  def : Property<"lvaluePath", LValuePathSerializationHelper> {
526    let Conditional = [{ hasLValuePath }];
527    let Read = [{
528      APValue::LValuePathSerializationHelper(node.getLValuePath(), elemTy)
529    }];
530  }
531  def : Creator<[{
532    (void)ctx;
533    APValue::LValueBase base;
534    if (hasBase) {
535      if (isTypeInfo) {
536        base = APValue::LValueBase::getTypeInfo(
537            TypeInfoLValue(typeInfo->getTypePtr()), *type);
538      } else if (isDynamicAlloc) {
539        base = APValue::LValueBase::getDynamicAlloc(
540            DynamicAllocLValue(*dynamicAlloc), *type);
541      } else if (isExpr) {
542        base = APValue::LValueBase(cast<Expr>(*stmt),
543                                   *callIndex, *version);
544      } else {
545        base = APValue::LValueBase(cast<ValueDecl>(*decl),
546                                   *callIndex, *version);
547      }
548    }
549    CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
550    APValue result;
551    result.MakeLValue();
552    if (!hasLValuePath) {
553      result.setLValue(base, offset, APValue::NoLValuePath{}, isNullPtr);
554      return result;
555    }
556    auto pathLength = lvaluePath->Path.size();
557    APValue::LValuePathEntry *path = result.setLValueUninit(
558        base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
559    llvm::copy(lvaluePath->Path, path);
560    return result;
561  }]>;
562}
563
564// Type cases for DeclarationName.
565def : PropertyTypeKind<DeclarationName, DeclarationNameKind,
566                       "node.getNameKind()">;
567let Class = PropertyTypeCase<DeclarationName, "Identifier"> in {
568  def : Property<"identifier", Identifier> {
569    let Read = [{ node.getAsIdentifierInfo() }];
570  }
571  def : Creator<[{
572    return DeclarationName(identifier);
573  }]>;
574}
575foreach count = ["Zero", "One", "Multi"] in {
576  let Class = PropertyTypeCase<DeclarationName, "ObjC"#count#"ArgSelector"> in {
577    def : Property<"selector", Selector> {
578      let Read = [{ node.getObjCSelector() }];
579    }
580    def : Creator<[{
581      return DeclarationName(selector);
582    }]>;
583  }
584}
585foreach kind = ["Constructor", "Destructor", "ConversionFunction"] in {
586  let Class = PropertyTypeCase<DeclarationName, "CXX"#kind#"Name"> in {
587    def : Property<"type", QualType> {
588      let Read = [{ node.getCXXNameType() }];
589    }
590    def : Creator<[{
591      return ctx.DeclarationNames.getCXX}]#kind#[{Name(
592               ctx.getCanonicalType(type));
593    }]>;
594  }
595}
596let Class = PropertyTypeCase<DeclarationName, "CXXDeductionGuideName"> in {
597  def : Property<"declaration", TemplateDeclRef> {
598    let Read = [{ node.getCXXDeductionGuideTemplate() }];
599  }
600  def : Creator<[{
601    return ctx.DeclarationNames.getCXXDeductionGuideName(declaration);
602  }]>;
603}
604let Class = PropertyTypeCase<DeclarationName, "CXXOperatorName"> in {
605  def : Property<"operatorKind", OverloadedOperatorKind> {
606    let Read = [{ node.getCXXOverloadedOperator() }];
607  }
608  def : Creator<[{
609    return ctx.DeclarationNames.getCXXOperatorName(operatorKind);
610  }]>;
611}
612let Class = PropertyTypeCase<DeclarationName, "CXXLiteralOperatorName"> in {
613  def : Property<"identifier", Identifier> {
614    let Read = [{ node.getCXXLiteralIdentifier() }];
615  }
616  def : Creator<[{
617    return ctx.DeclarationNames.getCXXLiteralOperatorName(identifier);
618  }]>;
619}
620let Class = PropertyTypeCase<DeclarationName, "CXXUsingDirective"> in {
621  def : Creator<[{
622    return DeclarationName::getUsingDirectiveName();
623  }]>;
624}
625
626// Type cases for TemplateName.
627def : PropertyTypeKind<TemplateName, TemplateNameKind, "node.getKind()">;
628let Class = PropertyTypeCase<TemplateName, "Template"> in {
629  def : Property<"declaration", TemplateDeclRef> {
630    let Read = [{ node.getAsTemplateDecl() }];
631  }
632  def : Creator<[{
633    return TemplateName(declaration);
634  }]>;
635}
636
637let Class = PropertyTypeCase<TemplateName, "UsingTemplate"> in {
638  def : Property<"foundDecl", UsingShadowDeclRef> {
639    let Read = [{ node.getAsUsingShadowDecl() }];
640  }
641  def : Creator<[{
642    return TemplateName(foundDecl);
643  }]>;
644}
645
646let Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in {
647  def : Property<"overloads", Array<NamedDeclRef>> {
648    let Read = [{ node.getAsOverloadedTemplate()->decls() }];
649  }
650  def : Creator<[{
651    // Copy into an UnresolvedSet to satisfy the interface.
652    UnresolvedSet<8> overloadSet;
653    for (auto overload : overloads) {
654      overloadSet.addDecl(overload);
655    }
656
657    return ctx.getOverloadedTemplateName(overloadSet.begin(),
658                                         overloadSet.end());
659  }]>;
660}
661let Class = PropertyTypeCase<TemplateName, "AssumedTemplate"> in {
662  def : Property<"name", DeclarationName> {
663    let Read = [{ node.getAsAssumedTemplateName()->getDeclName() }];
664  }
665  def : Creator<[{
666    return ctx.getAssumedTemplateName(name);
667  }]>;
668}
669let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
670  def : ReadHelper<[{
671    auto qtn = node.getAsQualifiedTemplateName();
672  }]>;
673  def : Property<"qualifier", NestedNameSpecifier> {
674    let Read = [{ qtn->getQualifier() }];
675  }
676  def : Property<"hasTemplateKeyword", Bool> {
677    let Read = [{ qtn->hasTemplateKeyword() }];
678  }
679  def : Property<"underlyingTemplateName", TemplateName> {
680    let Read = [{ qtn->getUnderlyingTemplate() }];
681  }
682  def : Creator<[{
683    return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
684                                        underlyingTemplateName);
685  }]>;
686}
687let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
688  def : ReadHelper<[{
689    auto dtn = node.getAsDependentTemplateName();
690  }]>;
691  def : Property<"qualifier", NestedNameSpecifier> {
692    let Read = [{ dtn->getQualifier() }];
693  }
694  def : Property<"identifier", Optional<Identifier>> {
695    let Read = [{ makeOptionalFromPointer(
696                    dtn->isIdentifier()
697                      ? dtn->getIdentifier()
698                      : nullptr) }];
699  }
700  def : Property<"operatorKind", OverloadedOperatorKind> {
701    let Conditional = [{ !identifier }];
702    let Read = [{ dtn->getOperator() }];
703  }
704  def : Creator<[{
705    if (identifier) {
706      return ctx.getDependentTemplateName(qualifier, *identifier);
707    } else {
708      return ctx.getDependentTemplateName(qualifier, *operatorKind);
709    }
710  }]>;
711}
712let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
713  def : ReadHelper<[{
714    auto parm = node.getAsSubstTemplateTemplateParm();
715  }]>;
716  def : Property<"replacement", TemplateName> {
717    let Read = [{ parm->getReplacement() }];
718  }
719  def : Property<"associatedDecl", DeclRef> {
720    let Read = [{ parm->getAssociatedDecl() }];
721  }
722  def : Property<"index", UInt32> {
723    let Read = [{ parm->getIndex() }];
724  }
725  def : Property<"packIndex", Optional<UInt32>> {
726    let Read = [{ parm->getPackIndex() }];
727  }
728  def : Creator<[{
729    return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
730  }]>;
731}
732let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
733  def : ReadHelper<[{
734    auto parm = node.getAsSubstTemplateTemplateParmPack();
735  }]>;
736  def : Property<"argumentPack", TemplateArgument> {
737    let Read = [{ parm->getArgumentPack() }];
738  }
739  def : Property<"associatedDecl", DeclRef> {
740    let Read = [{ parm->getAssociatedDecl() }];
741  }
742  def : Property<"index", UInt32> {
743    let Read = [{ parm->getIndex() }];
744  }
745  def : Property<"final", Bool> {
746    let Read = [{ parm->getFinal() }];
747  }
748  def : Creator<[{
749    return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index, final);
750  }]>;
751}
752
753// Type cases for TemplateArgument.
754def : PropertyTypeKind<TemplateArgument, TemplateArgumentKind,
755                       "node.getKind()">;
756let Class = PropertyTypeCase<TemplateArgument, "Null"> in {
757  def : Creator<[{
758    return TemplateArgument();
759  }]>;
760}
761let Class = PropertyTypeCase<TemplateArgument, "Type"> in {
762  def : Property<"type", QualType> {
763    let Read = [{ node.getAsType() }];
764  }
765  def : Property<"isDefaulted", Bool> {
766    let Read = [{ node.getIsDefaulted() }];
767  }
768  def : Creator<[{
769    return TemplateArgument(type, /* isNullPtr */ false, isDefaulted);
770  }]>;
771}
772let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in {
773  def : Property<"declaration", ValueDeclRef> {
774    let Read = [{ node.getAsDecl() }];
775  }
776  def : Property<"parameterType", QualType> {
777    let Read = [{ node.getParamTypeForDecl() }];
778  }
779  def : Property<"isDefaulted", Bool> {
780    let Read = [{ node.getIsDefaulted() }];
781  }
782  def : Creator<[{
783    return TemplateArgument(declaration, parameterType, isDefaulted);
784  }]>;
785}
786let Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in {
787  def : Property<"type", QualType> {
788    let Read = [{ node.getNullPtrType() }];
789  }
790  def : Property<"isDefaulted", Bool> {
791    let Read = [{ node.getIsDefaulted() }];
792  }
793  def : Creator<[{
794    return TemplateArgument(type, /*nullptr*/ true, isDefaulted);
795  }]>;
796}
797let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
798  def : Property<"value", APSInt> {
799    let Read = [{ node.getAsIntegral() }];
800  }
801  def : Property<"type", QualType> {
802    let Read = [{ node.getIntegralType() }];
803  }
804  def : Property<"isDefaulted", Bool> {
805    let Read = [{ node.getIsDefaulted() }];
806  }
807  def : Creator<[{
808    return TemplateArgument(ctx, value, type, isDefaulted);
809  }]>;
810}
811let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
812  def : Property<"name", TemplateName> {
813    let Read = [{ node.getAsTemplateOrTemplatePattern() }];
814  }
815  def : Property<"isDefaulted", Bool> {
816    let Read = [{ node.getIsDefaulted() }];
817  }
818  def : Creator<[{
819    return TemplateArgument(name, isDefaulted);
820  }]>;
821}
822let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in {
823  def : Property<"name", TemplateName> {
824    let Read = [{ node.getAsTemplateOrTemplatePattern() }];
825  }
826  def : Property<"numExpansions", Optional<UInt32>> {
827    let Read = [{
828      // Translate unsigned -> uint32_t just in case.
829      llvm::transformOptional(node.getNumTemplateExpansions(),
830                              [](unsigned i) { return uint32_t(i); })
831    }];
832  }
833  def : Property<"isDefaulted", Bool> {
834    let Read = [{ node.getIsDefaulted() }];
835  }
836  def : Creator<[{
837    auto numExpansionsUnsigned = llvm::transformOptional(
838        numExpansions, [](uint32_t i) { return unsigned(i); });
839
840    return TemplateArgument(name, numExpansionsUnsigned, isDefaulted);
841  }]>;
842}
843let Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
844  def : Property<"expression", ExprRef> {
845    let Read = [{ node.getAsExpr() }];
846  }
847  def : Property<"isDefaulted", Bool> {
848    let Read = [{ node.getIsDefaulted() }];
849  }
850  def : Creator<[{
851    return TemplateArgument(expression, isDefaulted);
852  }]>;
853}
854let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
855  def : Property<"elements", Array<TemplateArgument>> {
856    let Read = [{ node.pack_elements() }];
857  }
858  def : Creator<[{
859    // Copy the pack into the ASTContext.
860    TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
861    for (size_t i = 0, e = elements.size(); i != e; ++i)
862      ctxElements[i] = elements[i];
863    return TemplateArgument(llvm::ArrayRef(ctxElements, elements.size()));
864  }]>;
865}
866