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