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 def : Property<"typeConstraintConcept", Optional<ConceptDeclRef>> {
399 let Read = [{ makeOptionalFromPointer(
400 const_cast<const ConceptDecl*>(node->getTypeConstraintConcept())) }];
402 def : Property<"typeConstraintArguments", Array<TemplateArgument>> {
403 let Read = [{ node->getTypeConstraintArguments() }];
405 // FIXME: better enumerated value
406 // Only really required when the deduced type is null
407 def : Property<"dependence", UInt32> {
408 let Read = [{ !node->getDeducedType().isNull() ? 0 :
409 node->containsUnexpandedParameterPack() ? 2 :
410 node->isDependentType() ? 1 : 0 }];
414 return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
415 /*isDependentWithoutDeducedType*/ dependence > 0,
416 /*isPackWithoutDeducedType*/ dependence > 1,
417 makePointerFromOptional(typeConstraintConcept),
418 typeConstraintArguments);
422 let Class = DeducedTemplateSpecializationType in {
423 def : Property<"templateName", Optional<TemplateName>> {
424 let Read = [{ makeOptionalFromNullable(node->getTemplateName()) }];
426 def : Property<"deducedType", QualType> {
427 let Read = [{ node->getDeducedType() }];
429 // Only really required when the deduced type is null
430 def : Property<"dependent", Bool> {
431 let Read = [{ !node->getDeducedType().isNull()
432 ? false : node->isDependentType() }];
436 return ctx.getDeducedTemplateSpecializationType(
437 makeNullableFromOptional(templateName),
438 deducedType, dependent);
442 let Class = TagType in {
443 def : Property<"dependent", Bool> {
444 let Read = [{ node->isDependentType() }];
446 def : Property<"declaration", DeclRef> {
447 // Serializing a reference to the canonical declaration is apparently
448 // necessary to make module-merging work.
449 let Read = [{ node->getDecl()->getCanonicalDecl() }];
453 let Class = EnumType in {
455 QualType result = ctx.getEnumType(cast<EnumDecl>(declaration));
456 const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
461 let Class = RecordType in {
463 auto record = cast<RecordDecl>(declaration);
464 QualType result = ctx.getRecordType(record);
465 const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
470 let Class = ElaboratedType in {
471 def : Property<"keyword", ElaboratedTypeKeyword> {
472 let Read = [{ node->getKeyword() }];
474 def : Property<"qualifier", NestedNameSpecifier> {
475 let Read = [{ node->getQualifier() }];
477 def : Property<"namedType", QualType> {
478 let Read = [{ node->getNamedType() }];
480 def : Property<"ownedTag", Optional<TagDeclRef>> {
481 let Read = [{ makeOptionalFromPointer(
482 const_cast<const TagDecl *>(node->getOwnedTagDecl())) }];
486 return ctx.getElaboratedType(keyword, qualifier, namedType,
487 makePointerFromOptional(ownedTag));
491 let Class = InjectedClassNameType in {
492 def : Property<"declaration", DeclRef> {
493 // FIXME: drilling down to the canonical declaration is what the
494 // existing serialization code was doing, but it's not clear why.
495 let Read = [{ node->getDecl()->getCanonicalDecl() }];
497 def : Property<"injectedSpecializationType", QualType> {
498 let Read = [{ node->getInjectedSpecializationType() }];
502 // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
503 // for AST reading, too much interdependencies.
504 const Type *T = nullptr;
505 auto typeDecl = cast<CXXRecordDecl>(declaration);
506 for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl()) {
507 if (const Type *existing = DI->getTypeForDecl()) {
513 T = new (ctx, TypeAlignment)
514 InjectedClassNameType(typeDecl, injectedSpecializationType);
515 for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl())
516 DI->setTypeForDecl(T);
518 return QualType(T, 0);
522 let Class = ParenType in {
523 def : Property<"innerType", QualType> {
524 let Read = [{ node->getInnerType() }];
528 return ctx.getParenType(innerType);
532 let Class = MacroQualifiedType in {
533 def : Property<"underlyingType", QualType> {
534 let Read = [{ node->getUnderlyingType() }];
536 def : Property<"macroIdentifier", Identifier> {
537 let Read = [{ node->getMacroIdentifier() }];
541 return ctx.getMacroQualifiedType(underlyingType, macroIdentifier);
545 let Class = AttributedType in {
546 def : Property<"modifiedType", QualType> {
547 let Read = [{ node->getModifiedType() }];
549 def : Property<"equivalentType", QualType> {
550 let Read = [{ node->getEquivalentType() }];
552 def : Property<"attribute", AttrKind> {
553 let Read = [{ node->getAttrKind() }];
557 return ctx.getAttributedType(attribute, modifiedType, equivalentType);
561 let Class = DependentAddressSpaceType in {
562 def : Property<"pointeeType", QualType> {
563 let Read = [{ node->getPointeeType() }];
565 def : Property<"addressSpace", ExprRef> {
566 let Read = [{ node->getAddrSpaceExpr() }];
568 def : Property<"attributeLoc", SourceLocation> {
569 let Read = [{ node->getAttributeLoc() }];
573 return ctx.getDependentAddressSpaceType(pointeeType, addressSpace,
578 let Class = TemplateSpecializationType in {
579 def : Property<"dependent", Bool> {
580 let Read = [{ node->isDependentType() }];
582 def : Property<"templateName", TemplateName> {
583 let Read = [{ node->getTemplateName() }];
585 def : Property<"templateArguments", Array<TemplateArgument>> {
586 let Read = [{ node->template_arguments() }];
588 def : Property<"underlyingType", Optional<QualType>> {
591 ? llvm::Optional<QualType>(node->getAliasedType())
592 : node->isCanonicalUnqualified()
594 : llvm::Optional<QualType>(node->getCanonicalTypeInternal())
600 if (!underlyingType.hasValue()) {
601 result = ctx.getCanonicalTemplateSpecializationType(templateName,
604 result = ctx.getTemplateSpecializationType(templateName,
608 const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
613 let Class = DependentTemplateSpecializationType in {
614 def : Property<"keyword", ElaboratedTypeKeyword> {
615 let Read = [{ node->getKeyword() }];
617 def : Property<"qualifier", NestedNameSpecifier> {
618 let Read = [{ node->getQualifier() }];
620 def : Property<"name", Identifier> {
621 let Read = [{ node->getIdentifier() }];
623 def : Property<"templateArguments", Array<TemplateArgument>> {
624 let Read = [{ node->template_arguments() }];
628 return ctx.getDependentTemplateSpecializationType(keyword, qualifier,
629 name, templateArguments);
633 let Class = TemplateTypeParmType in {
634 def : Property<"depth", UInt32> {
635 let Read = [{ node->getDepth() }];
637 def : Property<"index", UInt32> {
638 let Read = [{ node->getIndex() }];
640 def : Property<"isParameterPack", Bool> {
641 let Read = [{ node->isParameterPack() }];
643 def : Property<"declaration", Optional<TemplateTypeParmDeclRef>> {
644 let Read = [{ makeOptionalFromPointer(
645 const_cast<const TemplateTypeParmDecl*>(node->getDecl())) }];
649 return ctx.getTemplateTypeParmType(depth, index, isParameterPack,
650 makePointerFromOptional(declaration));
654 let Class = SubstTemplateTypeParmType in {
655 def : Property<"replacedParameter", QualType> {
656 let Read = [{ QualType(node->getReplacedParameter(), 0) }];
658 def : Property<"replacementType", QualType> {
659 let Read = [{ node->getReplacementType() }];
663 // The call to getCanonicalType here existed in ASTReader.cpp, too.
664 return ctx.getSubstTemplateTypeParmType(
665 cast<TemplateTypeParmType>(replacedParameter),
666 ctx.getCanonicalType(replacementType));
670 let Class = PackExpansionType in {
671 def : Property<"pattern", QualType> {
672 let Read = [{ node->getPattern() }];
674 def : Property<"numExpansions", Optional<UInt32>> {
675 let Read = [{ node->getNumExpansions() }];
679 return ctx.getPackExpansionType(pattern, numExpansions);
683 let Class = SubstTemplateTypeParmPackType in {
684 def : Property<"replacedParameter", QualType> {
685 let Read = [{ QualType(node->getReplacedParameter(), 0) }];
687 def : Property<"replacementPack", TemplateArgument> {
688 let Read = [{ node->getArgumentPack() }];
692 return ctx.getSubstTemplateTypeParmPackType(
693 cast<TemplateTypeParmType>(replacedParameter),
698 let Class = BuiltinType in {
699 def : Property<"kind", BuiltinTypeKind> {
700 let Read = [{ node->getKind() }];
705 #define IMAGE_TYPE(IMGTYPE, ID, SINGLETON_ID, ACCESS, SUFFIX) \
706 case BuiltinType::ID: return ctx.SINGLETON_ID;
707 #include "clang/Basic/OpenCLImageTypes.def"
709 #define EXT_OPAQUE_TYPE(EXTTYPE, ID, EXT) \
710 case BuiltinType::ID: return ctx.ID##Ty;
711 #include "clang/Basic/OpenCLExtensionTypes.def"
713 #define SVE_TYPE(NAME, ID, SINGLETON_ID) \
714 case BuiltinType::ID: return ctx.SINGLETON_ID;
715 #include "clang/Basic/AArch64SVEACLETypes.def"
717 #define BUILTIN_TYPE(ID, SINGLETON_ID) \
718 case BuiltinType::ID: return ctx.SINGLETON_ID;
719 #include "clang/AST/BuiltinTypes.def"
721 llvm_unreachable("unreachable builtin case");
725 let Class = DependentNameType in {
726 def : Property<"keyword", ElaboratedTypeKeyword> {
727 let Read = [{ node->getKeyword() }];
729 def : Property<"qualifier", NestedNameSpecifier> {
730 let Read = [{ node->getQualifier() }];
732 def : Property<"name", Identifier> {
733 let Read = [{ node->getIdentifier() }];
735 def : Property<"underlyingType", Optional<QualType>> {
737 node->isCanonicalUnqualified()
739 : llvm::Optional<QualType>(node->getCanonicalTypeInternal())
744 QualType canon = (underlyingType
745 ? ctx.getCanonicalType(*underlyingType)
747 return ctx.getDependentNameType(keyword, qualifier, name, canon);
751 let Class = ObjCObjectType in {
752 def : Property<"baseType", QualType> {
753 let Read = [{ node->getBaseType() }];
755 def : Property<"typeArgsAsWritten", Array<QualType>> {
756 let Read = [{ node->getTypeArgsAsWritten() }];
758 def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
759 let Read = [{ node->getProtocols() }];
761 def : Property<"isKindOfTypeAsWritten", Bool> {
762 let Read = [{ node->isKindOfTypeAsWritten() }];
766 return ctx.getObjCObjectType(baseType, typeArgsAsWritten, qualifiers,
767 isKindOfTypeAsWritten);
771 let Class = ObjCInterfaceType in {
772 // We don't actually want any of the properties of the superclass.
774 let IgnoredProperties = [ "baseType", "typeArgsAsWritten",
775 "qualifiers", "isKindOfTypeAsWritten" ];
778 def : Property<"declaration", DeclRef> {
779 // FIXME: drilling down to the canonical declaration is what the
780 // existing serialization code was doing, but it's not clear why.
781 let Read = [{ node->getDecl()->getCanonicalDecl() }];
785 return ctx.getObjCInterfaceType(
786 cast<ObjCInterfaceDecl>(declaration->getCanonicalDecl()));
790 let Class = ObjCTypeParamType in {
791 def : Property<"declaration", ObjCTypeParamDeclRef> {
792 let Read = [{ node->getDecl() }];
794 def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
795 let Read = [{ node->getProtocols() }];
799 return ctx.getObjCTypeParamType(declaration, qualifiers);
803 let Class = ObjCObjectPointerType in {
804 def : Property<"pointeeType", QualType> {
805 let Read = [{ node->getPointeeType() }];
809 return ctx.getObjCObjectPointerType(pointeeType);
813 let Class = PipeType in {
814 def : Property<"elementType", QualType> {
815 let Read = [{ node->getElementType() }];
817 def : Property<"isReadOnly", Bool> {
818 let Read = [{ node->isReadOnly() }];
822 return ctx.getPipeType(elementType, isReadOnly);