1 //==--- TypeProperties.td - Type property definitions ---------------------===//
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
7 //===----------------------------------------------------------------------===//
9 include "clang/AST/PropertiesBase.td"
10 include "clang/Basic/TypeNodes.td"
12 let Class = ComplexType in {
13 def : Property<"elementType", QualType> {
14 let Read = [{ node->getElementType() }];
17 def : Creator<[{ return ctx.getComplexType(elementType); }]>;
20 let Class = PointerType in {
21 def : Property<"pointeeType", QualType> {
22 let Read = [{ node->getPointeeType() }];
25 def : Creator<[{ return ctx.getPointerType(pointeeType); }]>;
28 let Class = AdjustedType in {
29 def : Property<"originalType", QualType> {
30 let Read = [{ node->getOriginalType() }];
32 def : Property<"adjustedType", QualType> {
33 let Read = [{ node->getAdjustedType() }];
36 def : Creator<[{ return ctx.getAdjustedType(originalType, adjustedType); }]>;
39 let Class = DecayedType in {
41 // We don't need to serialize the adjusted type because we can always
42 // derive it by decaying the original type.
43 let IgnoredProperties = [ "adjustedType" ];
46 def : Creator<[{ return ctx.getAdjustedParameterType(originalType); }]>;
49 let Class = BlockPointerType in {
50 def : Property<"pointeeType", QualType> {
51 let Read = [{ node->getPointeeType() }];
54 def : Creator<[{ return ctx.getBlockPointerType(pointeeType); }]>;
57 let Class = ReferenceType in {
58 def : Property<"pointeeTypeAsWritten", QualType> {
59 let Read = [{ node->getPointeeTypeAsWritten() }];
63 let Class = LValueReferenceType in {
64 def : Property<"isSpelledAsLValue", Bool> {
65 let Read = [{ node->isSpelledAsLValue() }];
69 return ctx.getLValueReferenceType(pointeeTypeAsWritten,
74 let Class = RValueReferenceType in {
76 return ctx.getRValueReferenceType(pointeeTypeAsWritten);
80 let Class = MemberPointerType in {
81 def : Property<"pointeeType", QualType> {
82 let Read = [{ node->getPointeeType() }];
84 def : Property<"baseType", QualType> {
85 let Read = [{ QualType(node->getClass(), 0) }];
89 return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
93 let Class = ArrayType in {
94 def : Property<"elementType", QualType> {
95 let Read = [{ node->getElementType() }];
97 def : Property<"sizeModifier", ArraySizeModifier> {
98 let Read = [{ node->getSizeModifier() }];
100 def : Property<"indexQualifiers", Qualifiers> {
101 let Read = [{ Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) }];
105 let Class = ConstantArrayType in {
106 def : Property<"sizeValue", APInt> {
107 let Read = [{ node->getSize() }];
109 def : Property<"size", ExprRef> {
110 let Read = [{ node->getSizeExpr() }];
114 return ctx.getConstantArrayType(elementType, sizeValue, size,
116 indexQualifiers.getCVRQualifiers());
120 let Class = IncompleteArrayType in {
122 return ctx.getIncompleteArrayType(elementType, sizeModifier,
123 indexQualifiers.getCVRQualifiers());
127 let Class = VariableArrayType in {
128 def : Property<"leftBracketLoc", SourceLocation> {
129 let Read = [{ node->getLBracketLoc() }];
131 def : Property<"rightBracketLoc", SourceLocation> {
132 let Read = [{ node->getRBracketLoc() }];
134 def : Property<"size", ExprRef> {
135 let Read = [{ node->getSizeExpr() }];
139 return ctx.getVariableArrayType(elementType, size, sizeModifier,
140 indexQualifiers.getCVRQualifiers(),
141 SourceRange(leftBracketLoc,
146 let Class = DependentSizedArrayType in {
147 def : Property<"size", ExprRef> {
148 let Read = [{ node->getSizeExpr() }];
150 def : Property<"leftBracketLoc", SourceLocation> {
151 let Read = [{ node->getLBracketLoc() }];
153 def : Property<"rightBracketLoc", SourceLocation> {
154 let Read = [{ node->getRBracketLoc() }];
158 return ctx.getDependentSizedArrayType(elementType, size, sizeModifier,
159 indexQualifiers.getCVRQualifiers(),
160 SourceRange(leftBracketLoc,
165 let Class = VectorType in {
166 def : Property<"elementType", QualType> {
167 let Read = [{ node->getElementType() }];
169 def : Property<"numElements", UInt32> {
170 let Read = [{ node->getNumElements() }];
172 def : Property<"vectorKind", VectorKind> {
173 let Read = [{ node->getVectorKind() }];
177 return ctx.getVectorType(elementType, numElements, vectorKind);
181 let Class = DependentVectorType in {
182 def : Property<"elementType", QualType> {
183 let Read = [{ node->getElementType() }];
185 def : Property<"size", ExprRef> {
186 let Read = [{ node->getSizeExpr() }];
188 def : Property<"attributeLoc", SourceLocation> {
189 let Read = [{ node->getAttributeLoc() }];
191 def : Property<"vectorKind", VectorKind> {
192 let Read = [{ node->getVectorKind() }];
196 return ctx.getDependentVectorType(elementType, size, attributeLoc,
201 let Class = ExtVectorType in {
203 let IgnoredProperties = [ "vectorKind" ];
207 return ctx.getExtVectorType(elementType, numElements);
211 let Class = DependentSizedExtVectorType in {
212 def : Property<"elementType", QualType> {
213 let Read = [{ node->getElementType() }];
215 def : Property<"size", ExprRef> {
216 let Read = [{ node->getSizeExpr() }];
218 def : Property<"attributeLoc", SourceLocation> {
219 let Read = [{ node->getAttributeLoc() }];
223 return ctx.getDependentSizedExtVectorType(elementType, size, attributeLoc);
227 let Class = FunctionType in {
228 def : Property<"returnType", QualType> {
229 let Read = [{ node->getReturnType() }];
231 def : Property<"noReturn", Bool> {
232 let Read = [{ node->getExtInfo().getNoReturn() }];
234 def : Property<"hasRegParm", Bool> {
235 let Read = [{ node->getExtInfo().getHasRegParm() }];
237 def : Property<"regParm", UInt32> {
238 let Read = [{ node->getExtInfo().getRegParm() }];
240 def : Property<"callingConvention", CallingConv> {
241 let Read = [{ node->getExtInfo().getCC() }];
243 def : Property<"producesResult", Bool> {
244 let Read = [{ node->getExtInfo().getProducesResult() }];
246 def : Property<"noCallerSavedRegs", Bool> {
247 let Read = [{ node->getExtInfo().getNoCallerSavedRegs() }];
249 def : Property<"noCfCheck", Bool> {
250 let Read = [{ node->getExtInfo().getNoCfCheck() }];
254 let Class = FunctionNoProtoType in {
256 auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
257 callingConvention, producesResult,
258 noCallerSavedRegs, noCfCheck);
259 return ctx.getFunctionNoProtoType(returnType, extInfo);
263 let Class = FunctionProtoType in {
264 def : Property<"variadic", Bool> {
265 let Read = [{ node->isVariadic() }];
267 def : Property<"trailingReturn", Bool> {
268 let Read = [{ node->hasTrailingReturn() }];
270 def : Property<"methodQualifiers", Qualifiers> {
271 let Read = [{ node->getMethodQuals() }];
273 def : Property<"refQualifier", RefQualifierKind> {
274 let Read = [{ node->getRefQualifier() }];
276 def : Property<"exceptionSpecifier", ExceptionSpecInfo> {
277 let Read = [{ node->getExceptionSpecInfo() }];
279 def : Property<"parameters", Array<QualType>> {
280 let Read = [{ node->getParamTypes() }];
282 def : Property<"extParameterInfo", Array<ExtParameterInfo>> {
283 let Read = [{ node->hasExtParameterInfos()
284 ? node->getExtParameterInfos()
285 : llvm::ArrayRef<FunctionProtoType::ExtParameterInfo>() }];
289 auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
290 callingConvention, producesResult,
291 noCallerSavedRegs, noCfCheck);
292 FunctionProtoType::ExtProtoInfo epi;
293 epi.ExtInfo = extInfo;
294 epi.Variadic = variadic;
295 epi.HasTrailingReturn = trailingReturn;
296 epi.TypeQuals = methodQualifiers;
297 epi.RefQualifier = refQualifier;
298 epi.ExceptionSpec = exceptionSpecifier;
299 epi.ExtParameterInfos =
300 extParameterInfo.empty() ? nullptr : extParameterInfo.data();
301 return ctx.getFunctionType(returnType, parameters, epi);
305 let Class = AtomicType in {
306 def : Property<"valueType", QualType> {
307 let Read = [{ node->getValueType() }];
311 return ctx.getAtomicType(valueType);
315 let Class = UnresolvedUsingType in {
316 def : Property<"declaration", DeclRef> {
317 let Read = [{ node->getDecl() }];
321 return ctx.getTypeDeclType(cast<UnresolvedUsingTypenameDecl>(declaration));
325 let Class = TypedefType in {
326 def : Property<"declaration", DeclRef> {
327 let Read = [{ node->getDecl() }];
329 def : Property<"canonicalType", Optional<QualType>> {
330 let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }];
334 QualType finalCanonicalType =
335 canonicalType ? ctx.getCanonicalType(*canonicalType)
337 return ctx.getTypedefType(cast<TypedefNameDecl>(declaration),
342 let Class = TypeOfExprType in {
343 def : Property<"expression", ExprRef> {
344 let Read = [{ node->getUnderlyingExpr() }];
348 return ctx.getTypeOfExprType(expression);
352 let Class = TypeOfType in {
353 def : Property<"underlyingType", QualType> {
354 let Read = [{ node->getUnderlyingType() }];
358 return ctx.getTypeOfType(underlyingType);
362 let Class = DecltypeType in {
363 def : Property<"underlyingType", QualType> {
364 let Read = [{ node->getUnderlyingType() }];
366 def : Property<"expression", ExprRef> {
367 let Read = [{ node->getUnderlyingExpr() }];
371 return ctx.getDecltypeType(expression, underlyingType);
375 let Class = UnaryTransformType in {
376 def : Property<"baseType", QualType> {
377 let Read = [{ node->getBaseType() }];
379 def : Property<"underlyingType", QualType> {
380 let Read = [{ node->getUnderlyingType() }];
382 def : Property<"transform", UnaryTypeTransformKind> {
383 let Read = [{ node->getUTTKind() }];
387 return ctx.getUnaryTransformType(baseType, underlyingType, transform);
391 let Class = AutoType in {
392 def : Property<"deducedType", Optional<QualType>> {
393 let Read = [{ makeOptionalFromNullable(node->getDeducedType()) }];
395 def : Property<"keyword", AutoTypeKeyword> {
396 let Read = [{ node->getKeyword() }];
398 // FIXME: better enumerated value
399 // Only really required when the deduced type is null
400 def : Property<"dependence", UInt32> {
401 let Read = [{ !node->getDeducedType().isNull() ? 0 :
402 node->containsUnexpandedParameterPack() ? 2 :
403 node->isDependentType() ? 1 : 0 }];
407 return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
408 /*isDependentWithoutDeducedType*/ dependence > 0,
409 /*isPackWithoutDeducedType*/ dependence > 1);
413 let Class = DeducedTemplateSpecializationType in {
414 def : Property<"templateName", Optional<TemplateName>> {
415 let Read = [{ makeOptionalFromNullable(node->getTemplateName()) }];
417 def : Property<"deducedType", QualType> {
418 let Read = [{ node->getDeducedType() }];
420 // Only really required when the deduced type is null
421 def : Property<"dependent", Bool> {
422 let Read = [{ !node->getDeducedType().isNull()
423 ? false : node->isDependentType() }];
427 return ctx.getDeducedTemplateSpecializationType(
428 makeNullableFromOptional(templateName),
429 deducedType, dependent);
433 let Class = TagType in {
434 def : Property<"dependent", Bool> {
435 let Read = [{ node->isDependentType() }];
437 def : Property<"declaration", DeclRef> {
438 // Serializing a reference to the canonical declaration is apparently
439 // necessary to make module-merging work.
440 let Read = [{ node->getDecl()->getCanonicalDecl() }];
444 let Class = EnumType in {
446 QualType result = ctx.getEnumType(cast<EnumDecl>(declaration));
447 const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
452 let Class = RecordType in {
454 auto record = cast<RecordDecl>(declaration);
455 QualType result = ctx.getRecordType(record);
456 const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
461 let Class = ElaboratedType in {
462 def : Property<"keyword", ElaboratedTypeKeyword> {
463 let Read = [{ node->getKeyword() }];
465 def : Property<"qualifier", NestedNameSpecifier> {
466 let Read = [{ node->getQualifier() }];
468 def : Property<"namedType", QualType> {
469 let Read = [{ node->getNamedType() }];
471 def : Property<"ownedTag", Optional<TagDeclRef>> {
472 let Read = [{ makeOptionalFromPointer(
473 const_cast<const TagDecl *>(node->getOwnedTagDecl())) }];
477 return ctx.getElaboratedType(keyword, qualifier, namedType,
478 makePointerFromOptional(ownedTag));
482 let Class = InjectedClassNameType in {
483 def : Property<"declaration", DeclRef> {
484 // FIXME: drilling down to the canonical declaration is what the
485 // existing serialization code was doing, but it's not clear why.
486 let Read = [{ node->getDecl()->getCanonicalDecl() }];
488 def : Property<"injectedSpecializationType", QualType> {
489 let Read = [{ node->getInjectedSpecializationType() }];
493 // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
494 // for AST reading, too much interdependencies.
495 const Type *T = nullptr;
496 auto typeDecl = cast<CXXRecordDecl>(declaration);
497 for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl()) {
498 if (const Type *existing = DI->getTypeForDecl()) {
504 T = new (ctx, TypeAlignment)
505 InjectedClassNameType(typeDecl, injectedSpecializationType);
506 for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl())
507 DI->setTypeForDecl(T);
509 return QualType(T, 0);
513 let Class = ParenType in {
514 def : Property<"innerType", QualType> {
515 let Read = [{ node->getInnerType() }];
519 return ctx.getParenType(innerType);
523 let Class = MacroQualifiedType in {
524 def : Property<"underlyingType", QualType> {
525 let Read = [{ node->getUnderlyingType() }];
527 def : Property<"macroIdentifier", Identifier> {
528 let Read = [{ node->getMacroIdentifier() }];
532 return ctx.getMacroQualifiedType(underlyingType, macroIdentifier);
536 let Class = AttributedType in {
537 def : Property<"modifiedType", QualType> {
538 let Read = [{ node->getModifiedType() }];
540 def : Property<"equivalentType", QualType> {
541 let Read = [{ node->getEquivalentType() }];
543 def : Property<"attribute", AttrKind> {
544 let Read = [{ node->getAttrKind() }];
548 return ctx.getAttributedType(attribute, modifiedType, equivalentType);
552 let Class = DependentAddressSpaceType in {
553 def : Property<"pointeeType", QualType> {
554 let Read = [{ node->getPointeeType() }];
556 def : Property<"addressSpace", ExprRef> {
557 let Read = [{ node->getAddrSpaceExpr() }];
559 def : Property<"attributeLoc", SourceLocation> {
560 let Read = [{ node->getAttributeLoc() }];
564 return ctx.getDependentAddressSpaceType(pointeeType, addressSpace,
569 let Class = TemplateSpecializationType in {
570 def : Property<"dependent", Bool> {
571 let Read = [{ node->isDependentType() }];
573 def : Property<"templateName", TemplateName> {
574 let Read = [{ node->getTemplateName() }];
576 def : Property<"templateArguments", Array<TemplateArgument>> {
577 let Read = [{ node->template_arguments() }];
579 def : Property<"underlyingType", Optional<QualType>> {
582 ? llvm::Optional<QualType>(node->getAliasedType())
583 : node->isCanonicalUnqualified()
585 : llvm::Optional<QualType>(node->getCanonicalTypeInternal())
591 if (!underlyingType.hasValue()) {
592 result = ctx.getCanonicalTemplateSpecializationType(templateName,
595 result = ctx.getTemplateSpecializationType(templateName,
599 const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
604 let Class = DependentTemplateSpecializationType in {
605 def : Property<"keyword", ElaboratedTypeKeyword> {
606 let Read = [{ node->getKeyword() }];
608 def : Property<"qualifier", NestedNameSpecifier> {
609 let Read = [{ node->getQualifier() }];
611 def : Property<"name", Identifier> {
612 let Read = [{ node->getIdentifier() }];
614 def : Property<"templateArguments", Array<TemplateArgument>> {
615 let Read = [{ node->template_arguments() }];
619 return ctx.getDependentTemplateSpecializationType(keyword, qualifier,
620 name, templateArguments);
624 let Class = TemplateTypeParmType in {
625 def : Property<"depth", UInt32> {
626 let Read = [{ node->getDepth() }];
628 def : Property<"index", UInt32> {
629 let Read = [{ node->getIndex() }];
631 def : Property<"isParameterPack", Bool> {
632 let Read = [{ node->isParameterPack() }];
634 def : Property<"declaration", Optional<TemplateTypeParmDeclRef>> {
635 let Read = [{ makeOptionalFromPointer(
636 const_cast<const TemplateTypeParmDecl*>(node->getDecl())) }];
640 return ctx.getTemplateTypeParmType(depth, index, isParameterPack,
641 makePointerFromOptional(declaration));
645 let Class = SubstTemplateTypeParmType in {
646 def : Property<"replacedParameter", QualType> {
647 let Read = [{ QualType(node->getReplacedParameter(), 0) }];
649 def : Property<"replacementType", QualType> {
650 let Read = [{ node->getReplacementType() }];
654 // The call to getCanonicalType here existed in ASTReader.cpp, too.
655 return ctx.getSubstTemplateTypeParmType(
656 cast<TemplateTypeParmType>(replacedParameter),
657 ctx.getCanonicalType(replacementType));
661 let Class = PackExpansionType in {
662 def : Property<"pattern", QualType> {
663 let Read = [{ node->getPattern() }];
665 def : Property<"numExpansions", Optional<UInt32>> {
666 let Read = [{ node->getNumExpansions() }];
670 return ctx.getPackExpansionType(pattern, numExpansions);
674 let Class = SubstTemplateTypeParmPackType in {
675 def : Property<"replacedParameter", QualType> {
676 let Read = [{ QualType(node->getReplacedParameter(), 0) }];
678 def : Property<"replacementPack", TemplateArgument> {
679 let Read = [{ node->getArgumentPack() }];
683 return ctx.getSubstTemplateTypeParmPackType(
684 cast<TemplateTypeParmType>(replacedParameter),
689 let Class = BuiltinType in {
690 def : Property<"kind", BuiltinTypeKind> {
691 let Read = [{ node->getKind() }];
696 #define IMAGE_TYPE(IMGTYPE, ID, SINGLETON_ID, ACCESS, SUFFIX) \
697 case BuiltinType::ID: return ctx.SINGLETON_ID;
698 #include "clang/Basic/OpenCLImageTypes.def"
700 #define EXT_OPAQUE_TYPE(EXTTYPE, ID, EXT) \
701 case BuiltinType::ID: return ctx.ID##Ty;
702 #include "clang/Basic/OpenCLExtensionTypes.def"
704 #define SVE_TYPE(NAME, ID, SINGLETON_ID) \
705 case BuiltinType::ID: return ctx.SINGLETON_ID;
706 #include "clang/Basic/AArch64SVEACLETypes.def"
708 #define BUILTIN_TYPE(ID, SINGLETON_ID) \
709 case BuiltinType::ID: return ctx.SINGLETON_ID;
710 #include "clang/AST/BuiltinTypes.def"
712 llvm_unreachable("unreachable builtin case");
716 let Class = DependentNameType in {
717 def : Property<"keyword", ElaboratedTypeKeyword> {
718 let Read = [{ node->getKeyword() }];
720 def : Property<"qualifier", NestedNameSpecifier> {
721 let Read = [{ node->getQualifier() }];
723 def : Property<"name", Identifier> {
724 let Read = [{ node->getIdentifier() }];
726 def : Property<"underlyingType", Optional<QualType>> {
728 node->isCanonicalUnqualified()
730 : llvm::Optional<QualType>(node->getCanonicalTypeInternal())
735 QualType canon = (underlyingType
736 ? ctx.getCanonicalType(*underlyingType)
738 return ctx.getDependentNameType(keyword, qualifier, name, canon);
742 let Class = ObjCObjectType in {
743 def : Property<"baseType", QualType> {
744 let Read = [{ node->getBaseType() }];
746 def : Property<"typeArgsAsWritten", Array<QualType>> {
747 let Read = [{ node->getTypeArgsAsWritten() }];
749 def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
750 let Read = [{ node->getProtocols() }];
752 def : Property<"isKindOfTypeAsWritten", Bool> {
753 let Read = [{ node->isKindOfTypeAsWritten() }];
757 return ctx.getObjCObjectType(baseType, typeArgsAsWritten, qualifiers,
758 isKindOfTypeAsWritten);
762 let Class = ObjCInterfaceType in {
763 // We don't actually want any of the properties of the superclass.
765 let IgnoredProperties = [ "baseType", "typeArgsAsWritten",
766 "qualifiers", "isKindOfTypeAsWritten" ];
769 def : Property<"declaration", DeclRef> {
770 // FIXME: drilling down to the canonical declaration is what the
771 // existing serialization code was doing, but it's not clear why.
772 let Read = [{ node->getDecl()->getCanonicalDecl() }];
776 return ctx.getObjCInterfaceType(
777 cast<ObjCInterfaceDecl>(declaration->getCanonicalDecl()));
781 let Class = ObjCTypeParamType in {
782 def : Property<"declaration", ObjCTypeParamDeclRef> {
783 let Read = [{ node->getDecl() }];
785 def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
786 let Read = [{ node->getProtocols() }];
790 return ctx.getObjCTypeParamType(declaration, qualifiers);
794 let Class = ObjCObjectPointerType in {
795 def : Property<"pointeeType", QualType> {
796 let Read = [{ node->getPointeeType() }];
800 return ctx.getObjCObjectPointerType(pointeeType);
804 let Class = PipeType in {
805 def : Property<"elementType", QualType> {
806 let Read = [{ node->getElementType() }];
808 def : Property<"isReadOnly", Bool> {
809 let Read = [{ node->isReadOnly() }];
813 return ctx.getPipeType(elementType, isReadOnly);