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