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