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