[clang] [Clang] Make the result type of sizeof/pointer subtraction/size_t lit… (PR #136542)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 21 00:57:14 PDT 2025
https://github.com/YexuanXiao updated https://github.com/llvm/llvm-project/pull/136542
>From b9cc91971469dcf19bb926f6f53ae5a57d1109c3 Mon Sep 17 00:00:00 2001
From: YexuanXiao <bizwen at nykz.org>
Date: Mon, 21 Apr 2025 14:28:33 +0800
Subject: [PATCH 1/3] [Clang] Make the result type of sizeof/pointer
subtraction/size_t literals be typedefs instead of built-in types Includeing
the results of `sizeof`, `sizeof...`, `__datasizeof`, `__alignof`,
`_Alignof`, `alignof`, `_Countof`, `size_t` literals, and signed `size_t`
literals, as well as the results of pointer-pointer subtraction. It does not
affect any program output except for debugging information. The goal is to
enable clang and downstream tools such as clangd and clang-tidy to provide
more portable hints and diagnostics.
---
clang/include/clang/AST/ASTContext.h | 4 +++
clang/lib/AST/ASTContext.cpp | 29 ++++++++++++++++++++++
clang/lib/AST/ComparisonCategories.cpp | 30 ++++-------------------
clang/lib/AST/ExprCXX.cpp | 6 +++--
clang/lib/Sema/SemaExpr.cpp | 34 ++++++++++++++++++++------
5 files changed, 68 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 3c78833a3f069..0c133d45d3f5e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2442,6 +2442,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error,
unsigned *IntegerConstantArgs = nullptr) const;
+ QualType getCGlobalCXXStdNSTypedef(const NamespaceDecl *StdNS,
+ StringRef DefName,
+ QualType FallBack = {}) const;
+
/// Types and expressions required to build C++2a three-way comparisons
/// using operator<=>, including the values return by builtin <=> operators.
ComparisonCategories CompCategories;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 2836d68b05ff6..aa8ce0078d4d3 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12556,6 +12556,35 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
return getFunctionType(ResType, ArgTypes, EPI);
}
+QualType ASTContext::getCGlobalCXXStdNSTypedef(const NamespaceDecl *StdNS,
+ StringRef DefName,
+ QualType FallBack) const {
+ DeclContextLookupResult Lookup;
+ if (getLangOpts().C99) {
+ Lookup = getTranslationUnitDecl()->lookup(&Idents.get(DefName));
+ } else if (getLangOpts().CPlusPlus) {
+ if (StdNS == nullptr) {
+ auto LookupStdNS = getTranslationUnitDecl()->lookup(&Idents.get("std"));
+ if (!LookupStdNS.empty()) {
+ StdNS = dyn_cast<NamespaceDecl>(LookupStdNS.front());
+ }
+ }
+ if (StdNS) {
+ Lookup = StdNS->lookup(&Idents.get(DefName));
+ } else {
+ Lookup = getTranslationUnitDecl()->lookup(&Idents.get(DefName));
+ }
+ }
+ if (!Lookup.empty()) {
+ if (auto *TD = dyn_cast<TypedefNameDecl>(Lookup.front())) {
+ if (auto Result = getTypeDeclType(TD); !Result.isNull()) {
+ return Result;
+ }
+ }
+ }
+ return FallBack;
+}
+
static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
const FunctionDecl *FD) {
if (!FD->isExternallyVisible())
diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp
index 28244104d6636..46dcd6ac4261d 100644
--- a/clang/lib/AST/ComparisonCategories.cpp
+++ b/clang/lib/AST/ComparisonCategories.cpp
@@ -87,37 +87,17 @@ ComparisonCategoryInfo::ValueInfo *ComparisonCategoryInfo::lookupValueInfo(
return &Objects.back();
}
-static const NamespaceDecl *lookupStdNamespace(const ASTContext &Ctx,
- NamespaceDecl *&StdNS) {
- if (!StdNS) {
- DeclContextLookupResult Lookup =
- Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std"));
- if (!Lookup.empty())
- StdNS = dyn_cast<NamespaceDecl>(Lookup.front());
- }
- return StdNS;
-}
-
-static const CXXRecordDecl *lookupCXXRecordDecl(const ASTContext &Ctx,
- const NamespaceDecl *StdNS,
- ComparisonCategoryType Kind) {
- StringRef Name = ComparisonCategories::getCategoryString(Kind);
- DeclContextLookupResult Lookup = StdNS->lookup(&Ctx.Idents.get(Name));
- if (!Lookup.empty())
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Lookup.front()))
- return RD;
- return nullptr;
-}
-
const ComparisonCategoryInfo *
ComparisonCategories::lookupInfo(ComparisonCategoryType Kind) const {
auto It = Data.find(static_cast<char>(Kind));
if (It != Data.end())
return &It->second;
-
- if (const NamespaceDecl *NS = lookupStdNamespace(Ctx, StdNS))
- if (const CXXRecordDecl *RD = lookupCXXRecordDecl(Ctx, NS, Kind))
+ if (auto QT = Ctx.getCGlobalCXXStdNSTypedef(
+ nullptr, ComparisonCategories::getCategoryString(Kind));
+ !QT.isNull()) {
+ if (const auto *RD = QT->getAsCXXRecordDecl())
return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second;
+ }
return nullptr;
}
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 169f11b611066..306ddcb9f491a 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1700,8 +1700,10 @@ SizeOfPackExpr *SizeOfPackExpr::Create(ASTContext &Context,
ArrayRef<TemplateArgument> PartialArgs) {
void *Storage =
Context.Allocate(totalSizeToAlloc<TemplateArgument>(PartialArgs.size()));
- return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack,
- PackLoc, RParenLoc, Length, PartialArgs);
+ return new (Storage) SizeOfPackExpr(
+ Context.getCGlobalCXXStdNSTypedef(nullptr, "size_t",
+ Context.getSizeType()),
+ OperatorLoc, Pack, PackLoc, RParenLoc, Length, PartialArgs);
}
SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 01a021443c94f..d07be9f117957 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4026,10 +4026,20 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Does it fit in size_t?
if (ResultVal.isIntN(SizeTSize)) {
// Does it fit in ssize_t?
- if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0)
- Ty = Context.getSignedSizeType();
- else if (AllowUnsigned)
- Ty = Context.getSizeType();
+ if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0) {
+ auto SignedSize = Context.getSignedSizeType();
+ if (auto PtrDiff = Context.getCGlobalCXXStdNSTypedef(
+ getStdNamespace(), "ptrdiff_t");
+ Context.hasSameType(PtrDiff, SignedSize))
+ Ty = PtrDiff;
+ else if (auto SSize = Context.getCGlobalCXXStdNSTypedef(
+ getStdNamespace(), "ssize_t");
+ Context.hasSameType(SSize, SignedSize))
+ Ty = SSize;
+ } else if (AllowUnsigned) {
+ Ty = Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t",
+ Context.getSizeType());
+ }
Width = SizeTSize;
}
}
@@ -4702,7 +4712,10 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return new (Context) UnaryExprOrTypeTraitExpr(
- ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
+ ExprKind, TInfo,
+ Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t",
+ Context.getSizeType()),
+ OpLoc, R.getEnd());
}
ExprResult
@@ -4745,7 +4758,10 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return new (Context) UnaryExprOrTypeTraitExpr(
- ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd());
+ ExprKind, E,
+ Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t",
+ Context.getSizeType()),
+ OpLoc, E->getSourceRange().getEnd());
}
ExprResult
@@ -11353,8 +11369,10 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
}
}
- if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
- return Context.getPointerDiffType();
+ if (CompLHSTy)
+ *CompLHSTy = LHS.get()->getType();
+ return Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "ptrdiff_t",
+ Context.getPointerDiffType());
}
}
>From af5749ad5b94d30ee5252959a61ebf8602179826 Mon Sep 17 00:00:00 2001
From: YexuanXiao <bizwen at nykz.org>
Date: Mon, 21 Apr 2025 15:25:58 +0800
Subject: [PATCH 2/3] Revert ComparisonCategories.cpp because RecordDecl is not
TypedefNameDecl
---
clang/lib/AST/ComparisonCategories.cpp | 30 +++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp
index 46dcd6ac4261d..28244104d6636 100644
--- a/clang/lib/AST/ComparisonCategories.cpp
+++ b/clang/lib/AST/ComparisonCategories.cpp
@@ -87,17 +87,37 @@ ComparisonCategoryInfo::ValueInfo *ComparisonCategoryInfo::lookupValueInfo(
return &Objects.back();
}
+static const NamespaceDecl *lookupStdNamespace(const ASTContext &Ctx,
+ NamespaceDecl *&StdNS) {
+ if (!StdNS) {
+ DeclContextLookupResult Lookup =
+ Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std"));
+ if (!Lookup.empty())
+ StdNS = dyn_cast<NamespaceDecl>(Lookup.front());
+ }
+ return StdNS;
+}
+
+static const CXXRecordDecl *lookupCXXRecordDecl(const ASTContext &Ctx,
+ const NamespaceDecl *StdNS,
+ ComparisonCategoryType Kind) {
+ StringRef Name = ComparisonCategories::getCategoryString(Kind);
+ DeclContextLookupResult Lookup = StdNS->lookup(&Ctx.Idents.get(Name));
+ if (!Lookup.empty())
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Lookup.front()))
+ return RD;
+ return nullptr;
+}
+
const ComparisonCategoryInfo *
ComparisonCategories::lookupInfo(ComparisonCategoryType Kind) const {
auto It = Data.find(static_cast<char>(Kind));
if (It != Data.end())
return &It->second;
- if (auto QT = Ctx.getCGlobalCXXStdNSTypedef(
- nullptr, ComparisonCategories::getCategoryString(Kind));
- !QT.isNull()) {
- if (const auto *RD = QT->getAsCXXRecordDecl())
+
+ if (const NamespaceDecl *NS = lookupStdNamespace(Ctx, StdNS))
+ if (const CXXRecordDecl *RD = lookupCXXRecordDecl(Ctx, NS, Kind))
return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second;
- }
return nullptr;
}
>From 25418415bf97e292e3089a4232e01882a5ef5225 Mon Sep 17 00:00:00 2001
From: YexuanXiao <bizwen at nykz.org>
Date: Mon, 21 Apr 2025 16:01:01 +0800
Subject: [PATCH 3/3] hasSameType does not accept an empty type pointer, check
in advance that the type is not empty
---
clang/lib/Sema/SemaExpr.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d07be9f117957..bc8fe5c55d982 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4030,11 +4030,11 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
auto SignedSize = Context.getSignedSizeType();
if (auto PtrDiff = Context.getCGlobalCXXStdNSTypedef(
getStdNamespace(), "ptrdiff_t");
- Context.hasSameType(PtrDiff, SignedSize))
+ !PtrDiff.isNull() && Context.hasSameType(PtrDiff, SignedSize))
Ty = PtrDiff;
else if (auto SSize = Context.getCGlobalCXXStdNSTypedef(
getStdNamespace(), "ssize_t");
- Context.hasSameType(SSize, SignedSize))
+ !SSize.isNull() && Context.hasSameType(SSize, SignedSize))
Ty = SSize;
} else if (AllowUnsigned) {
Ty = Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t",
More information about the cfe-commits
mailing list