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 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 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
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
14 changes: 12 additions & 2 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// and bit count.
QualType getDependentBitIntType(bool Unsigned, Expr *BitsExpr) const;

QualType getPredefinedSugarType(uint32_t KD) const;

/// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
Expand Down Expand Up @@ -1952,6 +1954,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool IsDependent,
QualType Canon) const;

// The core language uses these types as the result types of some expressions,
// which are typically standard integer types and consistent with it's
// typedefs (if any).
QualType SizeType; // __size_t
QualType SignedSizeType; // __signed_size_t
QualType PtrdiffType; // __ptrdiff_t
public:
/// Return the unique reference to the type for the specified TagDecl
/// (struct/union/class/enum) decl.
Expand All @@ -1961,11 +1969,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
48 changes: 48 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2258,6 +2258,27 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
unsigned NumExpansions;
};

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

/// The "signed size_t" type.
SignedSizeT,

/// The "ptrdiff_t" type.
PtrdiffT
};

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 +2318,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
DependentTemplateSpecializationTypeBits;
PackExpansionTypeBitfields PackExpansionTypeBits;
CountAttributedTypeBitfields CountAttributedTypeBits;
PresefinedSugarTypeBitfields PredefinedSugarTypeBits;
};

private:
Expand Down Expand Up @@ -8054,6 +8076,32 @@ class DependentBitIntType final : public Type, public llvm::FoldingSetNode {
}
};

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

private:
PredefinedSugarType(Kind KD, QualType UnderlyingType)
: Type(PredefinedSugar, UnderlyingType->getCanonicalTypeInternal(),
TypeDependence::None) {
PredefinedSugarTypeBits.Kind = llvm::to_underlying(KD);
}

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

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

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

StringRef getName() const;

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> {};

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(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
73 changes: 57 additions & 16 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,23 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
MSGuidTagDecl = buildImplicitRecord("_GUID");
getTranslationUnitDecl()->addDecl(MSGuidTagDecl);
}

// 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.
if (!LangOpts.HLSL) {
// Using PredefinedSugarType makes these types as named sugar types rather
// than standard integer types, enabling better hints and diagnostics.
using Kind = PredefinedSugarType::Kind;
SizeType = getPredefinedSugarType(llvm::to_underlying(Kind::SizeT));
SignedSizeType =
getPredefinedSugarType(llvm::to_underlying(Kind::SignedSizeT));
PtrdiffType = getPredefinedSugarType(llvm::to_underlying(Kind::PtrdiffT));
} else {
SizeType = getFromTargetType(Target.getSizeType());
SignedSizeType = getFromTargetType(Target.getSignedSizeType());
PtrdiffType = getFromTargetType(Target.getPtrDiffType(LangAS::Default));
}
}

DiagnosticsEngine &ASTContext::getDiagnostics() const {
Expand Down Expand Up @@ -2528,8 +2545,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 @@ -5148,6 +5169,25 @@ QualType ASTContext::getDependentBitIntType(bool IsUnsigned,
return QualType(New, 0);
}

QualType ASTContext::getPredefinedSugarType(uint32_t KD) const {
using Kind = PredefinedSugarType::Kind;
auto getUnderlyingType = [](const ASTContext &Ctx, Kind KDI) -> QualType {
switch (KDI) {
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));
}
llvm_unreachable("unexpected kind");
};
auto *New = new (*this, alignof(PredefinedSugarType)) PredefinedSugarType(
static_cast<Kind>(KD), getUnderlyingType(*this, static_cast<Kind>(KD)));
Types.push_back(New);
return QualType(New, 0);
}

#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
Expand Down Expand Up @@ -6729,14 +6769,25 @@ 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 SizeType; }

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 SignedSizeType; }

/// 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 PtrdiffType; }

/// 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 @@ -6771,19 +6822,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 @@ -14536,6 +14574,9 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
DX->isCountInBytes(), DX->isOrNull(),
CDX);
}
case Type::PredefinedSugar:
// FIXME: Should this be reachable here?
return QualType();
}
llvm_unreachable("Unhandled Type Class");
}
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,12 @@ ExpectedType clang::ASTNodeImporter::VisitDependentBitIntType(
*ToNumBitsExprOrErr);
}

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

ExpectedType clang::ASTNodeImporter::VisitDependentSizedMatrixType(
const clang::DependentSizedMatrixType *T) {
Error Err = Error::success();
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/ASTStructuralEquivalence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,16 @@ 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;
else
assert(TP1->getCanonicalTypeInternal() ==
TP2->getCanonicalTypeInternal());
break;
}
} // end switch

return true;
Expand Down
Loading
Loading