https://github.com/YexuanXiao updated https://github.com/llvm/llvm-project/pull/136542
>From b9cc91971469dcf19bb926f6f53ae5a57d1109c3 Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Mon, 21 Apr 2025 14:28:33 +0800 Subject: [PATCH 1/9] [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 <biz...@nykz.org> Date: Mon, 21 Apr 2025 15:25:58 +0800 Subject: [PATCH 2/9] 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 <biz...@nykz.org> Date: Mon, 21 Apr 2025 16:01:01 +0800 Subject: [PATCH 3/9] 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", >From b22353968119714494aef0e331778ae72ecef2a8 Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Mon, 21 Apr 2025 17:10:15 +0800 Subject: [PATCH 4/9] Fix signed size_t literal fallback and try to fix tests --- clang/lib/Sema/SemaExpr.cpp | 2 ++ clang/test/AST/ast-dump-expr-json.cpp | 2 +- clang/test/AST/ast-dump-expr.cpp | 4 ++-- .../std-c-library-functions-arg-constraints.c | 16 ---------------- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index bc8fe5c55d982..c461fb0ff4419 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4036,6 +4036,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { getStdNamespace(), "ssize_t"); !SSize.isNull() && Context.hasSameType(SSize, SignedSize)) Ty = SSize; + else + Ty=SignedSize; } else if (AllowUnsigned) { Ty = Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t", Context.getSizeType()); diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index dd2fe1fcf60cf..151d7fc6e25f7 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -1545,7 +1545,7 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "qualType": "size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "Ts" diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 2efd0b5e8ac21..afdf4bf155b64 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -115,11 +115,11 @@ void Casting(const S *s) { template <typename... Ts> void UnaryExpressions(int *p) { sizeof...(Ts); - // CHECK: SizeOfPackExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> 'unsigned long' 0x{{[^ ]*}} Ts + // CHECK: SizeOfPackExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> 'std::size_t' 0x{{[^ ]*}} Ts noexcept(p - p); // CHECK: CXXNoexceptExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:17> 'bool' - // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:12, col:16> 'long' '-' + // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:12, col:16> 'std::ptrdiff_t' '-' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' // CHECK-NEXT: ImplicitCastExpr diff --git a/clang/test/Analysis/std-c-library-functions-arg-constraints.c b/clang/test/Analysis/std-c-library-functions-arg-constraints.c index 0b817dda98c72..5bb179d897c89 100644 --- a/clang/test/Analysis/std-c-library-functions-arg-constraints.c +++ b/clang/test/Analysis/std-c-library-functions-arg-constraints.c @@ -320,22 +320,6 @@ void test_buf_size_concrete_with_multiplication(void) { // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}} \ // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}} } -void test_buf_size_symbolic_with_multiplication(size_t s) { - short buf[3]; - __buf_size_arg_constraint_mul(buf, s, sizeof(short)); - clang_analyzer_eval(s * sizeof(short) <= 6); // \ - // report-warning{{TRUE}} \ - // bugpath-warning{{TRUE}} \ - // bugpath-note{{TRUE}} -} -void test_buf_size_symbolic_and_offset_with_multiplication(size_t s) { - short buf[3]; - __buf_size_arg_constraint_mul(buf + 1, s, sizeof(short)); - clang_analyzer_eval(s * sizeof(short) <= 4); // \ - // report-warning{{TRUE}} \ - // bugpath-warning{{TRUE}} \ - // bugpath-note{{TRUE}} -} // The minimum buffer size for this function is set to 10. int __buf_size_arg_constraint_concrete(const void *); >From 0eabf724c090088d827bb22875d1781c6015180d Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Mon, 21 Apr 2025 18:05:10 +0800 Subject: [PATCH 5/9] Try fix module --- clang/include/clang/AST/DeclContextInternals.h | 2 ++ clang/lib/Sema/SemaExpr.cpp | 4 ++-- clang/test/AST/ast-dump-expr-json.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/DeclContextInternals.h b/clang/include/clang/AST/DeclContextInternals.h index b17b7627ac90c..dd99a7d1b17af 100644 --- a/clang/include/clang/AST/DeclContextInternals.h +++ b/clang/include/clang/AST/DeclContextInternals.h @@ -244,6 +244,8 @@ class StoredDeclsList { // FIXME: Move the assert before the single decl case when we fix the // duplication coming from the ASTReader reading builtin types. + if(auto* T = dyn_cast<TypeDecl>(D);T!=nullptr&&T->getTypeForDecl()->isBuiltinType()) + return; assert(!llvm::is_contained(getLookupResult(), D) && "Already exists!"); // Determine if this declaration is actually a redeclaration. for (DeclListNode *N = getAsList(); /*return in loop*/; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c461fb0ff4419..85b227b592a26 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4036,8 +4036,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { getStdNamespace(), "ssize_t"); !SSize.isNull() && Context.hasSameType(SSize, SignedSize)) Ty = SSize; - else - Ty=SignedSize; + else + Ty = SignedSize; } else if (AllowUnsigned) { Ty = Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t", Context.getSizeType()); diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 151d7fc6e25f7..be298b1347dd3 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -1545,7 +1545,7 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "size_t" +// CHECK-NEXT: "qualType": "std::size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "Ts" >From 73db8f61830dd7f84a5343b4fe976d6d0d17482a Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Mon, 21 Apr 2025 18:23:04 +0800 Subject: [PATCH 6/9] Revert some failed changes --- clang/include/clang/AST/DeclContextInternals.h | 2 -- clang/test/AST/ast-dump-expr-json.cpp | 2 +- clang/test/AST/ast-dump-expr.cpp | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/AST/DeclContextInternals.h b/clang/include/clang/AST/DeclContextInternals.h index dd99a7d1b17af..b17b7627ac90c 100644 --- a/clang/include/clang/AST/DeclContextInternals.h +++ b/clang/include/clang/AST/DeclContextInternals.h @@ -244,8 +244,6 @@ class StoredDeclsList { // FIXME: Move the assert before the single decl case when we fix the // duplication coming from the ASTReader reading builtin types. - if(auto* T = dyn_cast<TypeDecl>(D);T!=nullptr&&T->getTypeForDecl()->isBuiltinType()) - return; assert(!llvm::is_contained(getLookupResult(), D) && "Already exists!"); // Determine if this declaration is actually a redeclaration. for (DeclListNode *N = getAsList(); /*return in loop*/; diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index be298b1347dd3..dd2fe1fcf60cf 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -1545,7 +1545,7 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "std::size_t" +// CHECK-NEXT: "qualType": "unsigned long" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "Ts" diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index afdf4bf155b64..2efd0b5e8ac21 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -115,11 +115,11 @@ void Casting(const S *s) { template <typename... Ts> void UnaryExpressions(int *p) { sizeof...(Ts); - // CHECK: SizeOfPackExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> 'std::size_t' 0x{{[^ ]*}} Ts + // CHECK: SizeOfPackExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> 'unsigned long' 0x{{[^ ]*}} Ts noexcept(p - p); // CHECK: CXXNoexceptExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:17> 'bool' - // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:12, col:16> 'std::ptrdiff_t' '-' + // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:12, col:16> 'long' '-' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' // CHECK-NEXT: ImplicitCastExpr >From 0005883632b8b479b7b4b8699ea990860f98900f Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Mon, 21 Apr 2025 19:09:06 +0800 Subject: [PATCH 7/9] Make the argument of operator new also size_t --- clang/lib/Sema/SemaDeclCXX.cpp | 5 +++-- clang/lib/Sema/SemaExpr.cpp | 15 +++++++++------ clang/test/AST/ast-dump-expr-json.cpp | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d4e48a14d13c2..98c17e128357a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -16715,8 +16715,9 @@ static bool CheckOperatorNewDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) return true; - CanQualType SizeTy = - SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType()); + CanQualType SizeTy = SemaRef.Context.getCanonicalType( + SemaRef.Context.getCGlobalCXXStdNSTypedef( + SemaRef.getStdNamespace(), "size_t", SemaRef.Context.getSizeType())); // C++ [basic.stc.dynamic.allocation]p1: // The return type shall be void*. The first parameter shall have type diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 85b227b592a26..cce2fef373a74 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4715,8 +4715,9 @@ 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.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t", - Context.getSizeType()), + Context.getCGlobalCXXStdNSTypedef( + getLangOpts().CPlusPlus ? getStdNamespace() : nullptr, "size_t", + Context.getSizeType()), OpLoc, R.getEnd()); } @@ -4761,8 +4762,9 @@ 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.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t", - Context.getSizeType()), + Context.getCGlobalCXXStdNSTypedef( + getLangOpts().CPlusPlus ? getStdNamespace() : nullptr, "size_t", + Context.getSizeType()), OpLoc, E->getSourceRange().getEnd()); } @@ -11373,8 +11375,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); - return Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "ptrdiff_t", - Context.getPointerDiffType()); + return Context.getCGlobalCXXStdNSTypedef( + getLangOpts().CPlusPlus ? getStdNamespace() : nullptr, "ptrdiff_t", + Context.getPointerDiffType()); } } diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index dd2fe1fcf60cf..151d7fc6e25f7 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -1545,7 +1545,7 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "qualType": "size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "Ts" >From 0e7470fd775a32f9644e4668407b8d3a53c84818 Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Mon, 21 Apr 2025 21:07:51 +0800 Subject: [PATCH 8/9] Revert some failed changes --- clang/lib/Sema/SemaDeclCXX.cpp | 5 ++--- clang/test/AST/ast-dump-expr-json.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 98c17e128357a..4e94b30cc8611 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -16715,9 +16715,8 @@ static bool CheckOperatorNewDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) return true; - CanQualType SizeTy = SemaRef.Context.getCanonicalType( - SemaRef.Context.getCGlobalCXXStdNSTypedef( - SemaRef.getStdNamespace(), "size_t", SemaRef.Context.getSizeType())); + CanQualType SizeTy = + SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType()); // C++ [basic.stc.dynamic.allocation]p1: // The return type shall be void*. The first parameter shall have type diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 151d7fc6e25f7..dd2fe1fcf60cf 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -1545,7 +1545,7 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "size_t" +// CHECK-NEXT: "qualType": "unsigned long" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "Ts" >From b7098ff2464d07ff53f2018d8eac8c5f5d03a2d3 Mon Sep 17 00:00:00 2001 From: YexuanXiao <biz...@nykz.org> Date: Tue, 22 Apr 2025 18:19:36 +0800 Subject: [PATCH 9/9] Try caching the lookup results --- clang/include/clang/AST/ASTContext.h | 13 +-- clang/lib/AST/ASTContext.cpp | 85 ++++++++++++------- clang/lib/AST/ExprCXX.cpp | 6 +- clang/lib/CodeGen/CGCall.cpp | 6 +- clang/lib/CodeGen/CGCoroutine.cpp | 4 +- clang/lib/CodeGen/CGObjCMac.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 38 ++------- .../Checkers/VLASizeChecker.cpp | 2 +- 8 files changed, 77 insertions(+), 79 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 0c133d45d3f5e..419e4b41bb3f1 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1218,6 +1218,11 @@ class ASTContext : public RefCountedBase<ASTContext> { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) CanQualType SingletonId; #include "clang/Basic/HLSLIntangibleTypes.def" + // Cache size_t and ptrdiff_t typedefs + // (C99 7.17), defined in <stddef.h>. + mutable QualType PtrDiffTy; + mutable QualType UnsignedSizeTy; + // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. @@ -1941,11 +1946,11 @@ class ASTContext : public RefCountedBase<ASTContext> { /// <stddef.h>. /// /// The sizeof operator requires this (C99 6.5.3.4p4). - CanQualType getSizeType() const; + QualType getSizeType() 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>. @@ -2442,10 +2447,6 @@ 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 aa8ce0078d4d3..1e5fa2aacb067 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6666,16 +6666,55 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { return getTypeDeclType(const_cast<TagDecl*>(Decl)); } +static QualType LookupCGlobalCXXStdNSTypedef(const ASTContext &Ctx, + StringRef DefName, + CanQualType const &CanType) { + DeclContextLookupResult Lookup; + if (Ctx.getLangOpts().C99) { + Lookup = Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get(DefName)); + } else if (Ctx.getLangOpts().CPlusPlus) { + const NamespaceDecl *StdNS = nullptr; + auto LookupStdNS = + Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std")); + if (!LookupStdNS.empty()) { + StdNS = dyn_cast<NamespaceDecl>(LookupStdNS.front()); + } + if (StdNS) { + Lookup = StdNS->lookup(&Ctx.Idents.get(DefName)); + } else { + Lookup = Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get(DefName)); + } + } + if (!Lookup.empty()) { + if (auto *TD = dyn_cast<TypedefNameDecl>(Lookup.front())) { + auto Result = Ctx.getTypeDeclType(TD); + if (!Result.isNull() && Ctx.hasSameType(Result, CanType) && + Ctx.getTypeAlign(Result) == Ctx.getTypeAlign(CanType)) { + return Result; + } + } + } + return QualType(); +} + /// 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 { - return getFromTargetType(Target->getSizeType()); +QualType ASTContext::getSizeType() const { + if (UnsignedSizeTy.isNull()) { + auto CanType = getFromTargetType(Target->getSizeType()); + if (auto TypeDef = LookupCGlobalCXXStdNSTypedef(*this, "size_t", CanType); + TypeDef.isNull()) + return CanType; + else + UnsignedSizeTy = TypeDef; + } + return UnsignedSizeTy; } /// Return the unique signed counterpart of the integer type /// corresponding to size_t. -CanQualType ASTContext::getSignedSizeType() const { +QualType ASTContext::getSignedSizeType() const { return getFromTargetType(Target->getSignedSizeType()); } @@ -6714,7 +6753,16 @@ QualType ASTContext::getUIntPtrType() const { /// 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)); + if (PtrDiffTy.isNull()) { + auto CanType = getFromTargetType(Target->getPtrDiffType(LangAS::Default)); + if (auto TypeDef = + LookupCGlobalCXXStdNSTypedef(*this, "ptrdiff_t", CanType); + TypeDef.isNull()) + return CanType; + else + PtrDiffTy = TypeDef; + } + return PtrDiffTy; } /// Return the unique unsigned counterpart of "ptrdiff_t" @@ -12556,35 +12604,6 @@ 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/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 306ddcb9f491a..169f11b611066 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1700,10 +1700,8 @@ SizeOfPackExpr *SizeOfPackExpr::Create(ASTContext &Context, ArrayRef<TemplateArgument> PartialArgs) { void *Storage = Context.Allocate(totalSizeToAlloc<TemplateArgument>(PartialArgs.size())); - return new (Storage) SizeOfPackExpr( - Context.getCGlobalCXXStdNSTypedef(nullptr, "size_t", - Context.getSizeType()), - OperatorLoc, Pack, PackLoc, RParenLoc, Length, PartialArgs); + return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack, + PackLoc, RParenLoc, Length, PartialArgs); } SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 8cb27420dd911..307c8ae2a5039 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -191,8 +191,10 @@ static void appendParameterTypes(const CodeGenTypes &CGT, assert(ExtInfos.size() == FPT->getNumParams()); for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { prefix.push_back(FPT->getParamType(I)); - if (ExtInfos[I].hasPassObjectSize()) - prefix.push_back(CGT.getContext().getSizeType()); + if (ExtInfos[I].hasPassObjectSize()) { + auto &Ctx = CGT.getContext(); + prefix.push_back(Ctx.getCanonicalType(Ctx.getSizeType())); + } } addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize, diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 0fc488e98aaf0..8d8807135b921 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -1002,14 +1002,14 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, } case llvm::Intrinsic::coro_size: { auto &Context = getContext(); - CanQualType SizeTy = Context.getSizeType(); + CanQualType SizeTy = Context.getCanonicalType(Context.getSizeType()); llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T); return RValue::get(Builder.CreateCall(F)); } case llvm::Intrinsic::coro_align: { auto &Context = getContext(); - CanQualType SizeTy = Context.getSizeType(); + CanQualType SizeTy = Context.getCanonicalType(Context.getSizeType()); llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T); return RValue::get(Builder.CreateCall(F)); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 1c23a8b4db918..6710f9b62ae8e 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -285,7 +285,7 @@ class ObjCCommonTypesHelper { SmallVector<CanQualType, 5> Params; Params.push_back(Ctx.VoidPtrTy); Params.push_back(Ctx.VoidPtrTy); - Params.push_back(Ctx.getSizeType()); + Params.push_back(Ctx.getCanonicalType(Ctx.getSizeType())); Params.push_back(Ctx.BoolTy); Params.push_back(Ctx.BoolTy); llvm::FunctionType *FTy = Types.GetFunctionType( diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index cce2fef373a74..c5b298a7a26e7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4025,23 +4025,11 @@ 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) { - auto SignedSize = Context.getSignedSizeType(); - if (auto PtrDiff = Context.getCGlobalCXXStdNSTypedef( - getStdNamespace(), "ptrdiff_t"); - !PtrDiff.isNull() && Context.hasSameType(PtrDiff, SignedSize)) - Ty = PtrDiff; - else if (auto SSize = Context.getCGlobalCXXStdNSTypedef( - getStdNamespace(), "ssize_t"); - !SSize.isNull() && Context.hasSameType(SSize, SignedSize)) - Ty = SSize; - else - Ty = SignedSize; - } else if (AllowUnsigned) { - Ty = Context.getCGlobalCXXStdNSTypedef(getStdNamespace(), "size_t", - Context.getSizeType()); - } + // Does it fit in ptrdiff_t? + if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0) + Ty = Context.getPointerDiffType(); + else if (AllowUnsigned) + Ty = Context.getSizeType(); Width = SizeTSize; } } @@ -4714,11 +4702,7 @@ 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.getCGlobalCXXStdNSTypedef( - getLangOpts().CPlusPlus ? getStdNamespace() : nullptr, "size_t", - Context.getSizeType()), - OpLoc, R.getEnd()); + ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd()); } ExprResult @@ -4761,11 +4745,7 @@ 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.getCGlobalCXXStdNSTypedef( - getLangOpts().CPlusPlus ? getStdNamespace() : nullptr, "size_t", - Context.getSizeType()), - OpLoc, E->getSourceRange().getEnd()); + ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd()); } ExprResult @@ -11375,9 +11355,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); - return Context.getCGlobalCXXStdNSTypedef( - getLangOpts().CPlusPlus ? getStdNamespace() : nullptr, "ptrdiff_t", - Context.getPointerDiffType()); + return Context.getPointerDiffType(); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index ba91b3632abbf..bdae5474fe450 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -94,7 +94,7 @@ ProgramStateRef VLASizeChecker::checkVLA(CheckerContext &C, ASTContext &Ctx = C.getASTContext(); SValBuilder &SVB = C.getSValBuilder(); - CanQualType SizeTy = Ctx.getSizeType(); + CanQualType SizeTy = Ctx.getCanonicalType(Ctx.getSizeType()); uint64_t SizeMax = SVB.getBasicValueFactory().getMaxValue(SizeTy)->getZExtValue(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits