Skip to content

[Clang] Make the SizeType, SignedSizeType and PtrdiffType be named sugar types instead of built-in types #143653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9628219
Enable __ptrdiff_t
YexuanXiao Jun 10, 2025
33f05ab
Enable __size_t and __unsigned_size_t
YexuanXiao Jun 11, 2025
7e2593e
Revert changes made outside the intended purpose
YexuanXiao Jun 11, 2025
bcc45f0
Add ASTContext::getCanonicalSizeType()
YexuanXiao Jun 11, 2025
9d6235b
Check typedefs are defined in the appropriate scope
YexuanXiao Jun 11, 2025
85cbd4a
Move ssize_t to the global scope, as it must ultimately be provided i…
YexuanXiao Jun 11, 2025
210fe3b
Fix code format
YexuanXiao Jun 12, 2025
ddd73d8
Clarifying support for C89
YexuanXiao Jun 12, 2025
6e207dd
Try add PredefinedSugarType
YexuanXiao Jun 13, 2025
1519032
Fix tests
YexuanXiao Jun 14, 2025
41f1433
Merge pull request #1 from YexuanXiao/predefined-sugar
YexuanXiao Jun 14, 2025
fc57313
Manually resolve conflicts
YexuanXiao Jun 14, 2025
c702c18
Add support for the new Type in FormatString
YexuanXiao Jun 14, 2025
4b62452
Enable __signed_size_t and __ptrdiff_t
YexuanXiao Jun 14, 2025
3ab170b
Update the comment to match the latest impl
YexuanXiao Jun 14, 2025
c26bb5f
Fix comment
YexuanXiao Jun 14, 2025
b53c418
Update tests to match the latest impl
YexuanXiao Jun 14, 2025
46a8ede
Fix the errors pointed out in the review
YexuanXiao Jun 14, 2025
aabc866
Fix enum-to-integer conversion
YexuanXiao Jun 14, 2025
f5acec2
Fix the test of clangd
YexuanXiao Jun 14, 2025
6d427d3
Fix code format
YexuanXiao Jun 14, 2025
b487226
Fix tests
YexuanXiao Jun 14, 2025
a60ff6e
Remove unnecessary #include added by clangd
YexuanXiao Jun 14, 2025
17ef365
Actively initialize SizeType, SignedSizeType, PtrdiffType instead of …
YexuanXiao Jun 15, 2025
dd2a256
Remove the unused function declaration and minor tweaks
YexuanXiao Jun 15, 2025
0bbc668
Use using declarations to expose protected members to simplify the code
YexuanXiao Jun 15, 2025
895efce
Resolve a conflict
YexuanXiao Jun 26, 2025
9ed218e
Temporary remove to resolve the conflict
YexuanXiao Jun 26, 2025
a60f96d
Merge branch 'main' into main
YexuanXiao Jun 26, 2025
faf82b1
Update ASTReader.cpp
YexuanXiao Jun 26, 2025
a10bd96
Fix the test of libc++
YexuanXiao Jun 28, 2025
6a473e0
Fix some simple issues
YexuanXiao Jun 28, 2025
9b9b90a
Fix other issues
YexuanXiao Jun 28, 2025
a753834
Enable HLSL
YexuanXiao Jun 28, 2025
816fef9
Use FoldingSetNode
YexuanXiao Jun 28, 2025
e8420f0
Improved based on the review
YexuanXiao Jun 29, 2025
2d1cb40
Assert out of bounds in advance
YexuanXiao Jun 29, 2025
1274282
Fixed the unset value
YexuanXiao Jun 29, 2025
6b8f27d
Oops, std::array should not be default-initialized
YexuanXiao Jun 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clang-tools-extra/clangd/unittests/HoverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2794,7 +2794,7 @@ TEST(Hover, All) {
})cpp",
[](HoverInfo &HI) {
HI.Name = "expression";
HI.Type = "unsigned long";
HI.Type = {"__size_t", "unsigned long"};
HI.Value = "1";
}},
{
Expand All @@ -2804,7 +2804,7 @@ TEST(Hover, All) {
})cpp",
[](HoverInfo &HI) {
HI.Name = "expression";
HI.Type = "unsigned long";
HI.Type = {"__size_t", "unsigned long"};
HI.Value = "1";
}},
{
Expand Down
13 changes: 11 additions & 2 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::ContextualFoldingSet<ArrayParameterType, ASTContext &>
ArrayParameterTypes;

/// Store the unique Type corresponding to each Kind.
mutable std::array<Type *,
llvm::to_underlying(PredefinedSugarType::Kind::Max)>
PredefinedSugarTypes{};

/// The set of nested name specifiers.
///
/// This set is managed by the NestedNameSpecifier class.
Expand Down Expand Up @@ -1567,6 +1572,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// and bit count.
QualType getDependentBitIntType(bool Unsigned, Expr *BitsExpr) const;

QualType getPredefinedSugarType(PredefinedSugarType::Kind KD) const;

/// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
Expand Down Expand Up @@ -1999,11 +2006,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// <stddef.h>.
///
/// The sizeof operator requires this (C99 6.5.3.4p4).
CanQualType getSizeType() const;
QualType getSizeType() const;

CanQualType getCanonicalSizeType() const;

/// Return the unique signed counterpart of
/// the integer type corresponding to size_t.
CanQualType getSignedSizeType() const;
QualType getSignedSizeType() const;

/// Return the unique type for "intmax_t" (C99 7.18.1.5), defined in
/// <stdint.h>.
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/AST/FormatString.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ class FormatSpecifier {

/// For a TypedefType QT, if it is a named integer type such as size_t,
/// assign the appropriate value to LM and return true.
static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
static bool namedTypeToLengthModifier(ASTContext &Ctx, QualType QT,
LengthModifier &LM);
};

} // end analyze_format_string namespace
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,8 @@ DEF_TRAVERSE_TYPE(BitIntType, {})
DEF_TRAVERSE_TYPE(DependentBitIntType,
{ TRY_TO(TraverseStmt(T->getNumBitsExpr())); })

DEF_TRAVERSE_TYPE(PredefinedSugarType, {})

#undef DEF_TRAVERSE_TYPE

// ----------------- TypeLoc traversal -----------------
Expand Down Expand Up @@ -1526,6 +1528,8 @@ DEF_TRAVERSE_TYPELOC(DependentBitIntType, {
TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr()));
})

DEF_TRAVERSE_TYPELOC(PredefinedSugarType, {})

#undef DEF_TRAVERSE_TYPELOC

// ----------------- Decl traversal -----------------
Expand Down
56 changes: 56 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2258,6 +2258,30 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
unsigned NumExpansions;
};

enum class PredefinedSugarKind {
/// The "size_t" type.
SizeT,

/// The signed integer type corresponding to "size_t".
SignedSizeT,

/// The "ptrdiff_t" type.
PtrdiffT,

// Indicates how many items the enum has.
Max
};

class PresefinedSugarTypeBitfields {
friend class PredefinedSugarType;

LLVM_PREFERRED_TYPE(TypeBitfields)
unsigned : NumTypeBits;

LLVM_PREFERRED_TYPE(PredefinedSugarKind)
unsigned Kind : 8;
};

class CountAttributedTypeBitfields {
friend class CountAttributedType;

Expand Down Expand Up @@ -2297,6 +2321,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
DependentTemplateSpecializationTypeBits;
PackExpansionTypeBitfields PackExpansionTypeBits;
CountAttributedTypeBitfields CountAttributedTypeBits;
PresefinedSugarTypeBitfields PredefinedSugarTypeBits;
};

private:
Expand Down Expand Up @@ -8038,6 +8063,37 @@ class DependentBitIntType final : public Type, public llvm::FoldingSetNode {
}
};

class PredefinedSugarType final : public Type {
public:
friend class ASTContext;
using Kind = PredefinedSugarKind;

private:
PredefinedSugarType(Kind KD, const IdentifierInfo *IdentName,
QualType CanonicalType)
: Type(PredefinedSugar, CanonicalType, TypeDependence::None),
Name(IdentName) {
PredefinedSugarTypeBits.Kind = llvm::to_underlying(KD);
}

static StringRef getName(Kind KD);

const IdentifierInfo *Name;

public:
bool isSugared() const { return true; }

QualType desugar() const { return getCanonicalTypeInternal(); }

Kind getKind() const { return Kind(PredefinedSugarTypeBits.Kind); }

const IdentifierInfo *getIdentifier() const { return Name; }

static bool classof(const Type *T) {
return T->getTypeClass() == PredefinedSugar;
}
};

/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
public:
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/TypeLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2767,6 +2767,10 @@ class DependentBitIntTypeLoc final
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentBitIntTypeLoc,
DependentBitIntType> {};

class PredefinedSugarTypeLoc final
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, PredefinedSugarTypeLoc,
PredefinedSugarType> {};
Comment on lines +2770 to +2772
Copy link
Contributor

@mizvekov mizvekov Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should ideally never be used in practice, as a PredefinedSugarType is never written in source code.
I wonder how hard it is to avoid it. Where is this coming up?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Predeclare all the type nodes.
#define ABSTRACT_TYPELOC(Class, Base)
#define TYPELOC(Class, Base) \
class Class##TypeLoc;
#include "clang/AST/TypeLocNodes.def"
declares it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but for the current uses of PredefinedSugarType in this patch, we should never have to produce these TypeLocs, since this type is never written in source code.

It would be interesting to watch for this. I suspect that if we end up producing it, it would be because of some workaround somewhere, where some function expects a TypeLoc / TypeSourceInfo and we just produce a trivial one.

Likewise, serializing these TypeLocs seems also to be unnecessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switch (TL.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, BASE)
#define TYPELOC(CLASS, BASE) \
case TypeLoc::CLASS: \
return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>());
#include "clang/AST/TypeLocNodes.def"
}
uses it, and TypeLocNodes.def is actually TypeNodes.td. I don't think there's currently a simple way to avoid it.


class ObjCProtocolLoc {
ObjCProtocolDecl *Protocol = nullptr;
SourceLocation Loc = SourceLocation();
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -1028,3 +1028,12 @@ let Class = DependentBitIntType in {
return ctx.getDependentBitIntType(isUnsigned, numBitsExpr);
}]>;
}

let Class = PredefinedSugarType in {
def : Property<"kind", UInt32> {
let Read = [{ static_cast<uint32_t>(node->getKind()) }];
}
def : Creator<[{
return ctx.getPredefinedSugarType(static_cast<PredefinedSugarType::Kind>(kind));
}]>;
}
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TypeNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,4 @@ def PipeType : TypeNode<Type>;
def AtomicType : TypeNode<Type>;
def BitIntType : TypeNode<Type>;
def DependentBitIntType : TypeNode<Type>, AlwaysDependent;
def PredefinedSugarType : TypeNode<Type>, NeverCanonical;
1 change: 1 addition & 0 deletions clang/include/clang/Serialization/TypeBitCodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57)
TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58)
TYPE_BIT_CODE(HLSLAttributedResource, HLSLRESOURCE_ATTRIBUTED, 59)
TYPE_BIT_CODE(HLSLInlineSpirv, HLSL_INLINE_SPIRV, 60)
TYPE_BIT_CODE(PredefinedSugar, PREDEFINED_SUGAR, 61)

#undef TYPE_BIT_CODE
80 changes: 64 additions & 16 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2595,8 +2595,12 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = static_cast<unsigned>(Width);
}
}

break;

case Type::PredefinedSugar:
return getTypeInfo(cast<PredefinedSugarType>(T)->desugar().getTypePtr());

case Type::Pipe:
Width = Target->getPointerWidth(LangAS::opencl_global);
Align = Target->getPointerAlign(LangAS::opencl_global);
Expand Down Expand Up @@ -5216,6 +5220,42 @@ QualType ASTContext::getDependentBitIntType(bool IsUnsigned,
return QualType(New, 0);
}

QualType
ASTContext::getPredefinedSugarType(PredefinedSugarType::Kind KD) const {
using Kind = PredefinedSugarType::Kind;

assert(KD != Kind::Max);

if (auto *Target = PredefinedSugarTypes[llvm::to_underlying(KD)];
Target != nullptr)
return QualType(Target, 0);

auto getCanonicalType = [](const ASTContext &Ctx, Kind KDI) -> QualType {
switch (KDI) {
// size_t (C99TC3 6.5.3.4), signed size_t (C++23 5.13.2) and
// ptrdiff_t (C99TC3 6.5.6) Although these types are not built-in, they
// are part of the core language and are widely used. Using
// PredefinedSugarType makes these types as named sugar types rather than
// standard integer types, enabling better hints and diagnostics.
case Kind::SizeT:
return Ctx.getFromTargetType(Ctx.Target->getSizeType());
case Kind::SignedSizeT:
return Ctx.getFromTargetType(Ctx.Target->getSignedSizeType());
case Kind::PtrdiffT:
return Ctx.getFromTargetType(Ctx.Target->getPtrDiffType(LangAS::Default));
case Kind::Max:;
}
llvm_unreachable("unexpected kind");
};

auto *New = new (*this, alignof(PredefinedSugarType))
PredefinedSugarType(KD, &Idents.get(PredefinedSugarType::getName(KD)),
getCanonicalType(*this, static_cast<Kind>(KD)));
Types.push_back(New);
PredefinedSugarTypes[llvm::to_underlying(KD)] = New;
return QualType(New, 0);
}

#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
Expand Down Expand Up @@ -6796,14 +6836,31 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {
/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
/// needs to agree with the definition in <stddef.h>.
CanQualType ASTContext::getSizeType() const {
QualType ASTContext::getSizeType() const {
return getPredefinedSugarType(PredefinedSugarType::Kind::SizeT);
}

CanQualType ASTContext::getCanonicalSizeType() const {
return getFromTargetType(Target->getSizeType());
}

/// Return the unique signed counterpart of the integer type
/// corresponding to size_t.
CanQualType ASTContext::getSignedSizeType() const {
return getFromTargetType(Target->getSignedSizeType());
QualType ASTContext::getSignedSizeType() const {
return getPredefinedSugarType(PredefinedSugarType::Kind::SignedSizeT);
}

/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
return getPredefinedSugarType(PredefinedSugarType::Kind::PtrdiffT);
}

/// Return the unique unsigned counterpart of "ptrdiff_t"
/// integer type. The standard (C11 7.21.6.1p7) refers to this type
/// in the definition of %tu format specifier.
QualType ASTContext::getUnsignedPointerDiffType() const {
return getFromTargetType(Target->getUnsignedPtrDiffType(LangAS::Default));
}

/// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5).
Expand Down Expand Up @@ -6838,19 +6895,6 @@ QualType ASTContext::getUIntPtrType() const {
return getCorrespondingUnsignedType(getIntPtrType());
}

/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
return getFromTargetType(Target->getPtrDiffType(LangAS::Default));
}

/// Return the unique unsigned counterpart of "ptrdiff_t"
/// integer type. The standard (C11 7.21.6.1p7) refers to this type
/// in the definition of %tu format specifier.
QualType ASTContext::getUnsignedPointerDiffType() const {
return getFromTargetType(Target->getUnsignedPtrDiffType(LangAS::Default));
}

/// Return the unique type for "pid_t" defined in
/// <sys/types.h>. We need this to compute the correct type for vfork().
QualType ASTContext::getProcessIDType() const {
Expand Down Expand Up @@ -14526,6 +14570,10 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
DX->isCountInBytes(), DX->isOrNull(),
CDX);
}
case Type::PredefinedSugar:
assert(cast<PredefinedSugarType>(X)->getKind() !=
cast<PredefinedSugarType>(Y)->getKind());
return QualType();
}
llvm_unreachable("Unhandled Type Class");
}
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,11 @@ ExpectedType clang::ASTNodeImporter::VisitDependentBitIntType(
*ToNumBitsExprOrErr);
}

ExpectedType clang::ASTNodeImporter::VisitPredefinedSugarType(
const clang::PredefinedSugarType *T) {
return Importer.getToContext().getPredefinedSugarType(T->getKind());
}

ExpectedType clang::ASTNodeImporter::VisitDependentSizedMatrixType(
const clang::DependentSizedMatrixType *T) {
Error Err = Error::success();
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/ASTStructuralEquivalence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
}
case Type::PredefinedSugar: {
const auto *TP1 = cast<PredefinedSugarType>(T1);
const auto *TP2 = cast<PredefinedSugarType>(T2);
if (TP1->getKind() != TP2->getKind())
return false;
break;
}
} // end switch

return true;
Expand Down
Loading
Loading