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