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