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