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