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