xref: /freebsd-src/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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 ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
76def AttrKind : EnumPropertyType<"attr::Kind">;
77def AutoTypeKeyword : EnumPropertyType;
78def Bool : PropertyType<"bool">;
79def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
80def CallingConv : EnumPropertyType;
81def DeclarationName : PropertyType;
82def DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">;
83def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; }
84  def CXXRecordDeclRef :
85    SubclassPropertyType<"CXXRecordDecl", DeclRef>;
86  def FunctionDeclRef :
87    SubclassPropertyType<"FunctionDecl", DeclRef>;
88  def NamedDeclRef :
89    SubclassPropertyType<"NamedDecl", DeclRef>;
90  def NamespaceDeclRef :
91    SubclassPropertyType<"NamespaceDecl", DeclRef>;
92  def NamespaceAliasDeclRef :
93    SubclassPropertyType<"NamespaceAliasDecl", DeclRef>;
94  def ObjCProtocolDeclRef :
95    SubclassPropertyType<"ObjCProtocolDecl", DeclRef>;
96  def ObjCTypeParamDeclRef :
97    SubclassPropertyType<"ObjCTypeParamDecl", DeclRef>;
98  def TagDeclRef :
99    SubclassPropertyType<"TagDecl", DeclRef>;
100  def TemplateDeclRef :
101    SubclassPropertyType<"TemplateDecl", DeclRef>;
102  def TemplateTypeParmDeclRef :
103    SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>;
104  def TemplateTemplateParmDeclRef :
105    SubclassPropertyType<"TemplateTemplateParmDecl", DeclRef>;
106  def ValueDeclRef :
107    SubclassPropertyType<"ValueDecl", DeclRef>;
108def ElaboratedTypeKeyword : EnumPropertyType;
109def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
110def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
111def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
112def NestedNameSpecifierKind :
113  EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
114def OverloadedOperatorKind : EnumPropertyType;
115def Qualifiers : PropertyType;
116def QualType : DefaultValuePropertyType;
117def RefQualifierKind : EnumPropertyType;
118def Selector : PropertyType;
119def SourceLocation : PropertyType;
120def StmtRef : RefPropertyType<"Stmt"> { let ConstWhenWriting = 1; }
121  def ExprRef : SubclassPropertyType<"Expr", StmtRef>;
122def TemplateArgument : PropertyType;
123def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
124def TemplateName : DefaultValuePropertyType;
125def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
126def UInt32 : CountPropertyType<"uint32_t">;
127def UInt64 : CountPropertyType<"uint64_t">;
128def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
129def VectorKind : EnumPropertyType<"VectorType::VectorKind">;
130
131def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> {
132  let BufferElementTypes = [ QualType ];
133}
134
135/// Arrays.  The corresponding C++ type is ArrayRef of the corresponding
136/// C++ type of the element.
137class Array<PropertyType element> : PropertyType {
138  PropertyType Element = element;
139  let BufferElementTypes = [ element ];
140}
141
142/// llvm::Optional<T>.  The corresponding C++ type is generally just the
143/// corresponding C++ type of the element.
144///
145/// Optional<Unsigned> may restrict the range of the operand for some
146/// serialization clients.
147class Optional<PropertyType element> : PropertyType {
148  PropertyType Element = element;
149  let PassByReference = element.PassByReference;
150}
151
152/// A property of an AST node.
153class Property<string name, PropertyType type> {
154  HasProperties Class;
155  string Name = name;
156  PropertyType Type = type;
157
158  /// A function for reading the property, expressed in terms of a variable
159  /// "node".
160  code Read;
161
162  /// Code specifying when this property is available.  Can be defined
163  /// in terms of other properties, in which case this property must be
164  /// read/written after those properties.  Using this will make the
165  /// value Optional when deserializing.
166  ///
167  /// FIXME: the emitter doesn't yet force dependent properties to be
168  /// read/written later; this only works if the properties used in the
169  /// condition happen to be written first.
170  code Conditional = "";
171}
172
173/// A rule for declaring helper variables when read properties from a
174/// value of this type.  Note that this means that this code is actually
175/// run when *writing* values of this type; however, naming this
176/// `ReadHelper` makes the connection to the `Read` operations on the
177/// properties much clearer.
178class ReadHelper<code _code> {
179  HasProperties Class;
180
181  /// Code which will be run when writing objects of this type before
182  /// writing any of the properties, specified in terms of a variable
183  /// `node`.
184  code Code = _code;
185}
186
187/// A rule for creating objects of this type.
188class Creator<code create> {
189  HasProperties Class;
190
191  /// A function for creating values of this kind, expressed in terms of a
192  /// variable `ctx` of type `ASTContext &`.  Must also refer to all of the
193  /// properties by name.
194  code Create = create;
195}
196
197/// A rule which overrides some of the normal rules.
198class Override {
199  HasProperties Class;
200
201  /// Properties from base classes that should be ignored.
202  list<string> IgnoredProperties = [];
203}
204
205/// A description of how to break a type into cases.  Providing this and
206/// an exhaustive list of the cases will cause AbstractBasic{Reader,Writer}
207/// to be generated with a default implementation of how to read the
208/// type.
209///
210/// Creator rules for the cases can additionally access a variable
211/// `kind` of the KindType.
212class PropertyTypeKind<PropertyType type,
213                       PropertyType kindType,
214                       string readCode> {
215  /// The type for which this describes cases.
216  PropertyType Type = type;
217
218  /// The type of this type's kind enum.
219  PropertyType KindType = kindType;
220
221  /// The property name to use for the kind.
222  string KindPropertyName = "kind";
223
224  /// An expression which reads the kind from a value, expressed in terms
225  /// of a variable `node`.
226  string Read = readCode;
227}
228
229/// One of the options for representing a particular type.
230class PropertyTypeCase<PropertyType type, string name> : HasProperties {
231  /// The type of which this is a case.
232  PropertyType Type = type;
233
234  /// The name of the case (a value of the type's kind enum).
235  string Name = name;
236}
237
238// Type cases for DeclarationName.
239def : PropertyTypeKind<DeclarationName, DeclarationNameKind,
240                       "node.getNameKind()">;
241let Class = PropertyTypeCase<DeclarationName, "Identifier"> in {
242  def : Property<"identifier", Identifier> {
243    let Read = [{ node.getAsIdentifierInfo() }];
244  }
245  def : Creator<[{
246    return DeclarationName(identifier);
247  }]>;
248}
249foreach count = ["Zero", "One", "Multi"] in {
250  let Class = PropertyTypeCase<DeclarationName, "ObjC"#count#"ArgSelector"> in {
251    def : Property<"selector", Selector> {
252      let Read = [{ node.getObjCSelector() }];
253    }
254    def : Creator<[{
255      return DeclarationName(selector);
256    }]>;
257  }
258}
259foreach kind = ["Constructor", "Destructor", "ConversionFunction"] in {
260  let Class = PropertyTypeCase<DeclarationName, "CXX"#kind#"Name"> in {
261    def : Property<"type", QualType> {
262      let Read = [{ node.getCXXNameType() }];
263    }
264    def : Creator<[{
265      return ctx.DeclarationNames.getCXX}]#kind#[{Name(
266               ctx.getCanonicalType(type));
267    }]>;
268  }
269}
270let Class = PropertyTypeCase<DeclarationName, "CXXDeductionGuideName"> in {
271  def : Property<"declaration", TemplateDeclRef> {
272    let Read = [{ node.getCXXDeductionGuideTemplate() }];
273  }
274  def : Creator<[{
275    return ctx.DeclarationNames.getCXXDeductionGuideName(declaration);
276  }]>;
277}
278let Class = PropertyTypeCase<DeclarationName, "CXXOperatorName"> in {
279  def : Property<"operatorKind", OverloadedOperatorKind> {
280    let Read = [{ node.getCXXOverloadedOperator() }];
281  }
282  def : Creator<[{
283    return ctx.DeclarationNames.getCXXOperatorName(operatorKind);
284  }]>;
285}
286let Class = PropertyTypeCase<DeclarationName, "CXXLiteralOperatorName"> in {
287  def : Property<"identifier", Identifier> {
288    let Read = [{ node.getCXXLiteralIdentifier() }];
289  }
290  def : Creator<[{
291    return ctx.DeclarationNames.getCXXLiteralOperatorName(identifier);
292  }]>;
293}
294let Class = PropertyTypeCase<DeclarationName, "CXXUsingDirective"> in {
295  def : Creator<[{
296    return DeclarationName::getUsingDirectiveName();
297  }]>;
298}
299
300// Type cases for TemplateName.
301def : PropertyTypeKind<TemplateName, TemplateNameKind, "node.getKind()">;
302let Class = PropertyTypeCase<TemplateName, "Template"> in {
303  def : Property<"declaration", TemplateDeclRef> {
304    let Read = [{ node.getAsTemplateDecl() }];
305  }
306  def : Creator<[{
307    return TemplateName(declaration);
308  }]>;
309}
310let Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in {
311  def : Property<"overloads", Array<NamedDeclRef>> {
312    let Read = [{ node.getAsOverloadedTemplate()->decls() }];
313  }
314  def : Creator<[{
315    // Copy into an UnresolvedSet to satisfy the interface.
316    UnresolvedSet<8> overloadSet;
317    for (auto overload : overloads) {
318      overloadSet.addDecl(overload);
319    }
320
321    return ctx.getOverloadedTemplateName(overloadSet.begin(),
322                                         overloadSet.end());
323  }]>;
324}
325let Class = PropertyTypeCase<TemplateName, "AssumedTemplate"> in {
326  def : Property<"name", DeclarationName> {
327    let Read = [{ node.getAsAssumedTemplateName()->getDeclName() }];
328  }
329  def : Creator<[{
330    return ctx.getAssumedTemplateName(name);
331  }]>;
332}
333let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
334  def : ReadHelper<[{
335    auto qtn = node.getAsQualifiedTemplateName();
336  }]>;
337  def : Property<"qualifier", NestedNameSpecifier> {
338    let Read = [{ qtn->getQualifier() }];
339  }
340  def : Property<"hasTemplateKeyword", Bool> {
341    let Read = [{ qtn->hasTemplateKeyword() }];
342  }
343  def : Property<"declaration", TemplateDeclRef> {
344    let Read = [{ qtn->getTemplateDecl() }];
345  }
346  def : Creator<[{
347    return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
348                                        declaration);
349  }]>;
350}
351let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
352  def : ReadHelper<[{
353    auto dtn = node.getAsDependentTemplateName();
354  }]>;
355  def : Property<"qualifier", NestedNameSpecifier> {
356    let Read = [{ dtn->getQualifier() }];
357  }
358  def : Property<"identifier", Optional<Identifier>> {
359    let Read = [{ makeOptionalFromPointer(
360                    dtn->isIdentifier()
361                      ? dtn->getIdentifier()
362                      : nullptr) }];
363  }
364  def : Property<"operatorKind", OverloadedOperatorKind> {
365    let Conditional = [{ !identifier }];
366    let Read = [{ dtn->getOperator() }];
367  }
368  def : Creator<[{
369    if (identifier) {
370      return ctx.getDependentTemplateName(qualifier, *identifier);
371    } else {
372      return ctx.getDependentTemplateName(qualifier, *operatorKind);
373    }
374  }]>;
375}
376let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
377  def : ReadHelper<[{
378    auto parm = node.getAsSubstTemplateTemplateParm();
379  }]>;
380  def : Property<"parameter", TemplateTemplateParmDeclRef> {
381    let Read = [{ parm->getParameter() }];
382  }
383  def : Property<"replacement", TemplateName> {
384    let Read = [{ parm->getReplacement() }];
385  }
386  def : Creator<[{
387    return ctx.getSubstTemplateTemplateParm(parameter, replacement);
388  }]>;
389}
390let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
391  def : ReadHelper<[{
392    auto parm = node.getAsSubstTemplateTemplateParmPack();
393  }]>;
394  def : Property<"parameterPack", TemplateTemplateParmDeclRef> {
395    let Read = [{ parm->getParameterPack() }];
396  }
397  def : Property<"argumentPack", TemplateArgument> {
398    let Read = [{ parm->getArgumentPack() }];
399  }
400  def : Creator<[{
401    return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack);
402  }]>;
403}
404
405// Type cases for TemplateArgument.
406def : PropertyTypeKind<TemplateArgument, TemplateArgumentKind,
407                       "node.getKind()">;
408let Class = PropertyTypeCase<TemplateArgument, "Null"> in {
409  def : Creator<[{
410    return TemplateArgument();
411  }]>;
412}
413let Class = PropertyTypeCase<TemplateArgument, "Type"> in {
414  def : Property<"type", QualType> {
415    let Read = [{ node.getAsType() }];
416  }
417  def : Creator<[{
418    return TemplateArgument(type);
419  }]>;
420}
421let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in {
422  def : Property<"declaration", ValueDeclRef> {
423    let Read = [{ node.getAsDecl() }];
424  }
425  def : Property<"parameterType", QualType> {
426    let Read = [{ node.getParamTypeForDecl() }];
427  }
428  def : Creator<[{
429    return TemplateArgument(declaration, parameterType);
430  }]>;
431}
432let Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in {
433  def : Property<"type", QualType> {
434    let Read = [{ node.getNullPtrType() }];
435  }
436  def : Creator<[{
437    return TemplateArgument(type, /*nullptr*/ true);
438  }]>;
439}
440let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
441  def : Property<"value", APSInt> {
442    let Read = [{ node.getAsIntegral() }];
443  }
444  def : Property<"type", QualType> {
445    let Read = [{ node.getIntegralType() }];
446  }
447  def : Creator<[{
448    return TemplateArgument(ctx, value, type);
449  }]>;
450}
451let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
452  def : Property<"name", TemplateName> {
453    let Read = [{ node.getAsTemplateOrTemplatePattern() }];
454  }
455  def : Creator<[{
456    return TemplateArgument(name);
457  }]>;
458}
459let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in {
460  def : Property<"name", TemplateName> {
461    let Read = [{ node.getAsTemplateOrTemplatePattern() }];
462  }
463  def : Property<"numExpansions", Optional<UInt32>> {
464    let Read = [{
465      // Translate unsigned -> uint32_t just in case.
466      node.getNumTemplateExpansions().map(
467        [](unsigned i) { return uint32_t(i); })
468    }];
469  }
470  def : Creator<[{
471    auto numExpansionsUnsigned =
472      numExpansions.map([](uint32_t i) { return unsigned(i); });
473    return TemplateArgument(name, numExpansionsUnsigned);
474  }]>;
475}
476let Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
477  def : Property<"expression", ExprRef> {
478    let Read = [{ node.getAsExpr() }];
479  }
480  def : Creator<[{
481    return TemplateArgument(expression);
482  }]>;
483}
484let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
485  def : Property<"elements", Array<TemplateArgument>> {
486    let Read = [{ node.pack_elements() }];
487  }
488  def : Creator<[{
489    // Copy the pack into the ASTContext.
490    TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
491    for (size_t i = 0, e = elements.size(); i != e; ++i)
492      ctxElements[i] = elements[i];
493    return TemplateArgument(llvm::makeArrayRef(ctxElements, elements.size()));
494  }]>;
495}
496