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