aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/DeclCXX.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-07-18[Clang][AST][NFC] Introduce `NamespaceBaseDecl` (#149123)Yanzuo Liu1-8/+12
Add `NamespaceBaseDecl` as common base class of `NamespaceDecl` and `NamespaceAliasDecl`. This simplifies `NestedNameSpecifier` a bit. Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
2025-07-12[Clang][AST][NFC] (`RecordDecl` -> `CXXRecordDecl`)`::isInjectedClassName` ↵Yanzuo Liu1-0/+10
(#148195) Move `RecordDecl::isInjectedClassName` to `CXXRecordDecl::isInjectedClassName`. C language doesn't have the term "injected class name". Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
2025-06-23[NFC][Clang][AST] Drop `llvm::` in front of `ArrayRef`/`MutableArrayRef` ↵Rahul Joshi1-4/+4
(#145207)
2025-05-15[NFC][Clang] Adopt simplified `getTrailingObjects` in DeclCXX (#140078)Rahul Joshi1-6/+4
- Adopt non-templated and ArrayRef returning forms of `getTrailingObjects`. - Replace some initialization loop with std::uninitialized_fill_n. - Remove unneeded `numTrailingObjects` for last trailing type.
2025-05-06[Clang] Implement the core language parts of P2786 - Trivial relocation ↵cor3ntin1-1/+6
(#127636) This adds - The parsing of `trivially_relocatable_if_eligible`, `replaceable_if_eligible` keywords - `__builtin_trivially_relocate`, implemented in terms of memmove. In the future this should - Add the appropriate start/end lifetime markers that llvm does not have (`start_lifetime_as`) - Add support for ptrauth when that's upstreamed - the `__builtin_is_cpp_trivially_relocatable` and `__builtin_is_replaceable` traits Fixes #127609
2025-05-02[Clang] incorrect assertion when checking template template parameter of a ↵cor3ntin1-1/+6
lambda (#138121) When a lambda is used in an alias declaration, we were trying to refer to its call operator. However, that could happen before (or during) the call operator is defined. So we should not assume a lambda always has a call operator. Fixes #136432 Fixes #137014 Fixes #138018
2025-04-15[PAC] Add support for __ptrauth type qualifier (#100830)Akira Hatanaka1-0/+27
The qualifier allows programmer to directly control how pointers are signed when they are stored in a particular variable. The qualifier takes three arguments: the signing key, a flag specifying whether address discrimination should be used, and a non-negative integer that is used for additional discrimination. ``` typedef void (*my_callback)(const void*); my_callback __ptrauth(ptrauth_key_process_dependent_code, 1, 0xe27a) callback; ``` Co-Authored-By: John McCall rjmccall@apple.com
2025-04-14[MS][clang] Revert vector deleting destructors support (#135611)Mariya Podchishchaeva1-6/+0
Finding operator delete[] is still problematic, without it the extension is a security hazard, so reverting until the problem with operator delete[] is figured out. This reverts the following PRs: Reland [MS][clang] Add support for vector deleting destructors (llvm#133451) [MS][clang] Make sure vector deleting dtor calls correct operator delete (llvm#133950) [MS][clang] Fix crash on deletion of array of pointers (llvm#134088) [clang] Do not diagnose unused deleted operator delete[] (llvm#134357) [MS][clang] Error about ambiguous operator delete[] only when required (llvm#135041)
2025-04-10[RFC] Initial implementation of P2719 (#113510)Oliver Hunt1-2/+35
This is a basic implementation of P2719: "Type-aware allocation and deallocation functions" described at http://wg21.link/P2719 The proposal includes some more details but the basic change in functionality is the addition of support for an additional implicit parameter in operators `new` and `delete` to act as a type tag. Tag is of type `std::type_identity<T>` where T is the concrete type being allocated. So for example, a custom type specific allocator for `int` say can be provided by the declaration of void *operator new(std::type_identity<int>, size_t, std::align_val_t); void operator delete(std::type_identity<int>, void*, size_t, std::align_val_t); However this becomes more powerful by specifying templated declarations, for example template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); template <typename T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t);); Where the operators being resolved will be the concrete type being operated over (NB. A completely unconstrained global definition as above is not recommended as it triggers many problems similar to a general override of the global operators). These type aware operators can be declared as either free functions or in class, and can be specified with or without the other implicit parameters, with overload resolution performed according to the existing standard parameter prioritisation, only with type parameterised operators having higher precedence than non-type aware operators. The only exception is destroying_delete which for reasons discussed in the paper we do not support type-aware variants by default.
2025-04-04[clang] Do not diagnose unused deleted operator delete[] (#134357)Mariya Podchishchaeva1-2/+1
For vector deleting dtors support we now also search and save operator delete[]. Avoid diagnosing deleted operator delete[] when doing that because vector deleting dtors are only called when delete[] is present and whenever delete[] is present in the TU it will be diagnosed correctly. Fixes https://github.com/llvm/llvm-project/issues/134265
2025-04-03[clang] support pack expansions for trailing requires clauses (#133190)Matheus Izvekov1-14/+19
2025-04-02[MS][clang] Make sure vector deleting dtor calls correct operator delete ↵Mariya Podchishchaeva1-0/+7
(#133950) During additional testing I spotted that vector deleting dtor calls operator delete, not operator delete[] when performing array deletion. This patch fixes that.
2025-02-18[Clang][P1061] Consolidate ResolvedUnpexandedPackExpr into ↵Jason Rice1-3/+6
FunctionParmPackExpr (#125394) This merges the functionality of ResolvedUnexpandedPackExpr into FunctionParmPackExpr. I also added a test to show that https://github.com/llvm/llvm-project/issues/125103 should be fixed with this. I put the removal of ResolvedUnexpandedPackExpr in its own commit. Let me know what you think. Fixes #125103
2025-02-15[HLSL] Implement HLSL intialization list support (#123141)Chris B1-0/+12
This PR implements HLSL's initialization list behvaior as specified in the draft language specifcation under [*Decl.Init.Agg*](https://microsoft.github.io/hlsl-specs/specs/hlsl.html#Decl.Init.Agg). This behavior is a bit unusual for C/C++ because intermediate braces in initializer lists are ignored and a whole array of additional conversions occur unintuitively to how initializaiton works in C. The implementaiton in this PR generates a valid C/C++ initialization list AST for the HLSL initializer so that there are no changes required to Clang's CodeGen to support this. This design will also allow us to use Clang's rewrite to convert HLSL initializers to valid C/C++ initializers that are equivalent. It does have the downside that it will generate often redundant accesses during codegen. The IR optimizer is extremely good at eliminating those so this will have no impact on the final executable performance. There is some opportunity for optimizing the initializer list generation that we could consider in subsequent commits. One notable opportunity would be to identify aggregate objects that occur in the same place in both initializers and do not require converison, those aggregates could be initialized as aggregates rather than fully scalarized. Closes #56067 --------- Co-authored-by: Finn Plummer <50529406+inbelic@users.noreply.github.com> Co-authored-by: Helena Kotas <hekotas@microsoft.com> Co-authored-by: Justin Bogner <mail@justinbogner.com>
2025-01-29[Clang][P1061] Add stuctured binding packs (#121417)Jason Rice1-4/+12
This is an implementation of P1061 Structure Bindings Introduce a Pack without the ability to use packs outside of templates. There is a couple of ways the AST could have been sliced so let me know what you think. The only part of this change that I am unsure of is the serialization/deserialization stuff. I followed the implementation of other Exprs, but I do not really know how it is tested. Thank you for your time considering this. --------- Co-authored-by: Yanzuo Liu <zwuis@outlook.com>
2025-01-27[clang] Track source deduction guide for alias template deduction guides ↵antangelo1-7/+11
(#123875) For deduction guides generated from alias template CTAD, store the deduction guide they were originated from. The source kind is also maintained for future expansion in CTAD from inherited constructors. This tracking is required to determine whether an alias template already has a deduction guide corresponding to some deduction guide on the original template, in order to support deduction guides for the alias from deduction guides declared after the initial usage.
2025-01-25[clang] Migrate away from PointerUnion::dyn_cast (NFC) (#124425)Kazu Hirata1-4/+6
Note that PointerUnion::dyn_cast has been soft deprecated in PointerUnion.h: // FIXME: Replace the uses of is(), get() and dyn_cast() with // isa<T>, cast<T> and the llvm::dyn_cast<T> This patch migrates uses of PointerUnion::dyn_cast to dyn_cast_if_present (see the definition of PointerUnion::dyn_cast). Note that we cannot use dyn_cast in any of the migrations in this patch; placing assert(!X.isNull()); just before any of dyn_cast_if_present in this patch triggers some failure in check-clang.
2025-01-14Add Clang attribute to ensure that fields are initialized explicitly (#102040)higher-performance1-0/+39
This is a new Clang-specific attribute to ensure that field initializations are performed explicitly. For example, if we have ``` struct B { [[clang::explicit]] int f1; }; ``` then the diagnostic would trigger if we do `B b{};`: ``` field 'f1' is left uninitialized, but was marked as requiring initialization ``` This prevents callers from accidentally forgetting to initialize fields, particularly when new fields are added to the class.
2025-01-11Reapply "[clang] Avoid re-evaluating field bitwidth" (#122289)Timm Baeder1-1/+1
2025-01-09[C++20] Destroying delete and deleted destructors (#118800)Aaron Ballman1-0/+22
When a destroying delete overload is selected, the destructor is not automatically called. Therefore, the destructor can be deleted without causing the program to be ill-formed. Fixes #46818
2025-01-08Revert "[clang] Avoid re-evaluating field bitwidth (#117732)"Timm Bäder1-1/+1
This reverts commit 81fc3add1e627c23b7270fe2739cdacc09063e54. This breaks some LLDB tests, e.g. SymbolFile/DWARF/x86/no_unique_address-with-bitfields.cpp: lldb: ../llvm-project/clang/lib/AST/Decl.cpp:4604: unsigned int clang::FieldDecl::getBitWidthValue() const: Assertion `isa<ConstantExpr>(getBitWidth())' failed.
2025-01-08[clang] Avoid re-evaluating field bitwidth (#117732)Timm Baeder1-1/+1
Save the bitwidth value as a `ConstantExpr` with the value set. Remove the `ASTContext` parameter from `getBitWidthValue()`, so the latter simply returns the value from the `ConstantExpr` instead of constant-evaluating the bitwidth expression every time it is called.
2024-12-03Reapply "[clang] Fix name lookup for dependent bases" (#118003)Vladislav Belov1-2/+0
Unlike the previous version (https://github.com/llvm/llvm-project/pull/114978), this patch also removes an unnecessary assert that causes Clang to crash when compiling such tests. (clang/lib/AST/DeclCXX.cpp) https://lab.llvm.org/buildbot/#/builders/52/builds/4021 ```c++ template <class T> class X { public: X() = default; virtual ~X() = default; virtual int foo(int x, int y, T &entry) = 0; void bar() { struct Y : public X<T> { Y() : X() {} int foo(int, int, T &) override { return 42; } }; } }; ``` the assertions: ```c++ llvm-project/clang/lib/AST/DeclCXX.cpp:2508: void clang::CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *): Assertion `!MD->getParent()->isDependentContext() && "Can't add an overridden method to a class template!"' failed. ``` I believe that this assert is unnecessary and contradicts the logic of this patch. After its removal, Clang was successfully built using itself, and all tests passed.
2024-11-28[Clang] Fix constexpr-ness on implicitly deleted destructors (#116359)A. Jiang1-4/+9
In C++20, a defaulted but implicitly deleted destructor is constexpr if and only if the class has no virtual base class. This hasn't been changed in C++23 by P2448R2. Constexpr-ness on a deleted destructor affects almost nothing. The `__is_literal` intrinsic is related, while the corresponding `std::is_literal_type(_v)` utility has been removed in C++20. A recently added example in `test/AST/ByteCode/cxx23.cpp` will become valid, and the example is already accepted by GCC. Clang currently behaves correctly in C++23 mode, because the constexpr-ness on defaulted destructor is relaxed by P2448R2. But we should make similar relaxation for an implicitly deleted destructor. Fixes #85550.
2024-11-24[AST] Migrate away from PointerUnion::{is,get} (NFC) (#117469)Kazu Hirata1-3/+3
Note that PointerUnion::{is,get} have been soft deprecated in PointerUnion.h: // FIXME: Replace the uses of is(), get() and dyn_cast() with // isa<T>, cast<T> and the llvm::dyn_cast<T> I'm not touching PointerUnion::dyn_cast for now because it's a bit complicated; we could blindly migrate it to dyn_cast_if_present, but we should probably use dyn_cast when the operand is known to be non-null.
2024-11-17[AST] Remove unused includes (NFC) (#116549)Kazu Hirata1-1/+0
Identified with misc-include-cleaner.
2024-11-06Revert "Reapply "[Clang][Sema] Refactor collection of multi-level template ↵Krystian Stasiowski1-8/+6
argument lists (#106585, #111173)" (#111852)" (#115159) This reverts commit 2bb3d3a3f32ffaef3d9b6a27db7f1941f0cb1136.
2024-11-06Revert "Reapply "[Clang][Sema] Always use latest redeclaration of primary ↵Krystian Stasiowski1-2/+2
template" (#114569)" (#115156) This reverts commit b24650e814e55d90acfc40acf045456c98f32b9c.
2024-11-01Reapply "[Clang][Sema] Always use latest redeclaration of primary template" ↵Krystian Stasiowski1-2/+2
(#114569) This patch reapplies #114258, fixing an infinite recursion bug in `ASTImporter` that occurs when importing the primary template of a class template specialization when the latest redeclaration of that template is a friend declaration in the primary template.
2024-10-30Revert "[Clang][Sema] Always use latest redeclaration of primary template" ↵Felipe de Azevedo Piovezan1-2/+2
(#114304) Clang importer doesn't seem to work well with this change, see discussion in the original PR. Reverts llvm/llvm-project#114258
2024-10-30[Clang][Sema] Always use latest redeclaration of primary template (#114258)Krystian Stasiowski1-2/+2
This patch fixes a couple of regressions introduced in #111852. Consider: ``` template<typename T> struct A { template<bool U> static constexpr bool f() requires U { return true; } }; template<> template<bool U> constexpr bool A<short>::f() requires U { return A<long>::f<U>(); } template<> template<bool U> constexpr bool A<long>::f() requires U { return true; } static_assert(A<short>::f<true>()); // crash here ``` This crashes because when collecting template arguments from the _first_ declaration of `A<long>::f<true>` for constraint checking, we don't add the template arguments from the enclosing class template specialization because there exists another redeclaration that is a member specialization. This also fixes the following example, which happens for a similar reason: ``` // input.cppm export module input; export template<int N> constexpr int f(); template<int N> struct A { template<int J> friend constexpr int f(); }; template struct A<0>; template<int N> constexpr int f() { return N; } ``` ``` // input.cpp import input; static_assert(f<1>() == 1); // error: static assertion failed ```
2024-10-24[clang] Use {} instead of std::nullopt to initialize empty ArrayRef (#109399)Jay Foad1-3/+2
Follow up to #109133.
2024-10-22[HLSL][NFC] Move IsIntangibleType from SemaHLSL to Type to make it ↵Helena Kotas1-1/+2
accessible outside of Sema (#113206) Moves `IsIntangibleType` from SemaHLSL to Type class and renames it to `isHLSLIntangibleType`. The existing `isHLSLIntangibleType` is renamed to `isHLSLBuiltinIntangibleType` and updated to return true only for the builtin `__hlsl_resource_t` type. This change makes `isHLSLIntangibleType` functionality accessible outside of Sema, for example from clang CodeGen.
2024-10-22[clang] Allow class with anonymous union member to be ↵Rajveer Singh Bharadwaj1-1/+7
const-default-constructible even if a union member has a default member initializer (#95854) (#96301) Resolves #95854 -- As per https://eel.is/c++draft/dcl.init#general-8.3
2024-10-15[HLSL] Make HLSLAttributedResourceType canonical and add code paths to ↵Helena Kotas1-3/+3
convert HLSL types to DirectX target types (#110327) Translates `RWBuffer` and `StructuredBuffer` resources buffer types to DirectX target types `dx.TypedBuffer` and `dx.RawBuffer`. Includes a change of `HLSLAttributesResourceType` from 'sugar' type to full canonical type. This is required for codegen and other clang infrastructure to work property on HLSL resource types. Fixes #95952 (part 2/2)
2024-10-11Reapply "[Clang][Sema] Refactor collection of multi-level template argument ↵Krystian Stasiowski1-6/+8
lists (#106585, #111173)" (#111852) This patch reapplies #111173, fixing a bug when instantiating dependent expressions that name a member template that is later explicitly specialized for a class specialization that is implicitly instantiated. The bug is addressed by adding the `hasMemberSpecialization` function, which return `true` if _any_ redeclaration is a member specialization. This is then used when determining the instantiation pattern for a specialization of a template, and when collecting template arguments for a specialization of a template.
2024-10-09Revert "Reapply "[Clang][Sema] Refactor collection of multi-level template ↵Krystian Stasiowski1-14/+6
argument lists (#106585)" (#111173)" (#111766) This reverts commit 4da8ac34f76e707ab94380b94f616457cfd2cb83.
2024-10-08Reapply "[Clang][Sema] Refactor collection of multi-level template argument ↵Krystian Stasiowski1-6/+14
lists (#106585)" (#111173) Reapplies #106585, fixing an issue where non-dependent names of member templates appearing prior to that member template being explicitly specialized for an implicitly instantiated class template specialization would incorrectly use the definition of the explicitly specialized member template.
2024-10-08[Clang] Instantiate the correct lambda call operator (#110446)Sirraide1-3/+32
This is a fix for the following issue: when a lambda’s class type is merged across modules (e.g. because it is defined in a template in the GMF of some module `A`, and some other module `B` both imports `A` and has the same template in its GMF), then `getLambdaCallOperator()` might return the wrong operator (e.g. while compiling `B`, the lambda’s class type would be the one attached to `B`’s GMF, but the call operator ends up being the one attached to `A`’s GMF). This causes issues in situations where the call operator is in a template and accesses declarations in the surrounding context: when those declarations are instantated, a mapping is introduced from the original node in the template to that of the instantiation. If such an instantiation happens in `B`, and we then try to instantiate `A`’s call operator, any nodes in that call operator refer to declarations in the template in `A`, but the `LocalInstantiationScope` only contains mappings for declarations in `B`! This causes the following assertion (for godbolt links and more, see the issue below): ``` Assertion `isa<LabelDecl>(D) && "declaration not instantiated in this scope"' failed. ``` We now walk the redecl chain of the call operator to find the one that is in the same module as the record decl. This fixes #110401.
2024-10-01[Clang] Implement CWG 2707 "Deduction guides cannot have a trailing ↵Younan Zhang1-4/+5
requires-clause" (#110473) Closes https://github.com/llvm/llvm-project/issues/98595
2024-09-04[HLSL] Implement '__builtin_hlsl_is_intangible' type trait (#104544)Helena Kotas1-1/+16
Implements `__builtin_hlsl_is_intangible` type trait. HLSL intangible types are special implementation-defined types such as resource handles or samplers. Any class that is an array of intangible type or contains base class or members of intangible types is also an intangible type. Fixes #[102954](https://github.com/llvm/llvm-project/issues/102954)
2024-08-01[Clang] Fix definition of layout-compatible to ignore empty classes (#92103)Mital Ashok1-0/+36
Also changes the behaviour of `__builtin_is_layout_compatible` None of the historic nor the current definition of layout-compatible classes mention anything about base classes (other than implicitly through being standard-layout) and are defined in terms of members, not direct members.
2024-07-23[Clang] Do not attempt to access the `DefinitionData` of an incomplete type ↵Oleksandr T.1-0/+3
(#99998) We were asserting here because we were trying to access the `DefinitionData` of an incomplete type in the `Visit` lambda in `CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType`. The code that creates `FieldDecl`s always marks them as invalid if their type is incomplete, so checking whether the field decl whose type we’re about to look at is invalid fixes this issue. Fixes #99868.
2024-07-15[Clang][AST] Move NamespaceDecl bits to DeclContext (#98567)Krystian Stasiowski1-27/+4
Currently, `NamespaceDecl` has a member `AnonOrFirstNamespaceAndFlags` which stores a few pieces of data: - a bit indicating whether the namespace was declared `inline`, and - a bit indicating whether the namespace was declared as a _nested-namespace-definition_, and - a pointer a `NamespaceDecl` that either stores: - a pointer to the first declaration of that namespace if the declaration is no the first declaration, or - a pointer to the unnamed namespace that inhabits the namespace otherwise. `Redeclarable` already stores a pointer to the first declaration of an entity, so it's unnecessary to store this in `NamespaceDecl`. `DeclContext` has 8 bytes in which various bitfields can be stored for a declaration, so it's not necessary to store these in `NamespaceDecl` either. We only need to store a pointer to the unnamed namespace that inhabits the first declaration of a namespace. This patch moves the two bits currently stored in `NamespaceDecl` to `DeclContext`, and only stores a pointer to the unnamed namespace that inhabits a namespace in the first declaration of that namespace. Since `getOriginalNamespace` always returns the same `NamespaceDecl` as `getFirstDecl`, this function is removed to avoid confusion.
2024-07-01[Clang] [NFC] Use range-based for loops (#96831)MagentaTreehouse1-32/+31
Use range-based for loops. In addition, extracted a loop from `CXXRecordDecl::completeDefinition` to eliminate the `Done` flag, and only construct `MyFinalOverriders` when `FinalOverriders` is null.
2024-06-07[serialization] no transitive decl change (#92083)Chuanqi Xu1-2/+2
Following of https://github.com/llvm/llvm-project/pull/86912 The motivation of the patch series is that, for a module interface unit `X`, when the dependent modules of `X` changes, if the changes is not relevant with `X`, we hope the BMI of `X` won't change. For the specific patch, we hope if the changes was about irrelevant declaration changes, we hope the BMI of `X` won't change. **However**, I found the patch itself is not very useful in practice, since the adding or removing declarations, will change the state of identifiers and types in most cases. That said, for the most simple example, ``` // partA.cppm export module m:partA; // partA.v1.cppm export module m:partA; export void a() {} // partB.cppm export module m:partB; export void b() {} // m.cppm export module m; export import :partA; export import :partB; // onlyUseB; export module onlyUseB; import m; export inline void onluUseB() { b(); } ``` the BMI of `onlyUseB` will change after we change the implementation of `partA.cppm` to `partA.v1.cppm`. Since `partA.v1.cppm` introduces new identifiers and types (the function prototype). So in this patch, we have to write the tests as: ``` // partA.cppm export module m:partA; export int getA() { ... } export int getA2(int) { ... } // partA.v1.cppm export module m:partA; export int getA() { ... } export int getA(int) { ... } export int getA2(int) { ... } // partB.cppm export module m:partB; export void b() {} // m.cppm export module m; export import :partA; export import :partB; // onlyUseB; export module onlyUseB; import m; export inline void onluUseB() { b(); } ``` so that the new introduced declaration `int getA(int)` doesn't introduce new identifiers and types, then the BMI of `onlyUseB` can keep unchanged. While it looks not so great, the patch should be the base of the patch to erase the transitive change for identifiers and types since I don't know how can we introduce new types and identifiers without introducing new declarations. Given how tightly the relationship between declarations, types and identifiers, I think we can only reach the ideal state after we made the series for all of the three entties. The design of the patch is similar to https://github.com/llvm/llvm-project/pull/86912, which extends the 32-bit DeclID to 64-bit and use the higher bits to store the module file index and the lower bits to store the Local Decl ID. A slight difference is that we only use 48 bits to store the new DeclID since we try to use the higher 16 bits to store the module ID in the prefix of Decl class. Previously, we use 32 bits to store the module ID and 32 bits to store the DeclID. I don't want to allocate additional space so I tried to make the additional space the same as 64 bits. An potential interesting thing here is about the relationship between the module ID and the module file index. I feel we can get the module file index by the module ID. But I didn't prove it or implement it. Since I want to make the patch itself as small as possible. We can make it in the future if we want. Another change in the patch is the new concept Decl Index, which means the index of the very big array `DeclsLoaded` in ASTReader. Previously, the index of a loaded declaration is simply the Decl ID minus PREDEFINED_DECL_NUMs. So there are some places they got used ambiguously. But this patch tried to split these two concepts. As https://github.com/llvm/llvm-project/pull/86912 did, the change will increase the on-disk PCM file sizes. As the declaration ID may be the most IDs in the PCM file, this can have the biggest impact on the size. In my experiments, this change will bring 6.6% increase of the on-disk PCM size. No compile-time performance regression observed. Given the benefits in the motivation example, I think the cost is worthwhile.
2024-06-07Revert "[serialization] no transitive decl change (#92083)"Chuanqi Xu1-2/+2
This reverts commit 5c104879c1a98eeb845c03e7c45206bd48e88f0c. The ArmV7 bot is complaining the change breaks the alignment.
2024-06-07[serialization] no transitive decl change (#92083)Chuanqi Xu1-2/+2
Following of https://github.com/llvm/llvm-project/pull/86912 The motivation of the patch series is that, for a module interface unit `X`, when the dependent modules of `X` changes, if the changes is not relevant with `X`, we hope the BMI of `X` won't change. For the specific patch, we hope if the changes was about irrelevant declaration changes, we hope the BMI of `X` won't change. **However**, I found the patch itself is not very useful in practice, since the adding or removing declarations, will change the state of identifiers and types in most cases. That said, for the most simple example, ``` // partA.cppm export module m:partA; // partA.v1.cppm export module m:partA; export void a() {} // partB.cppm export module m:partB; export void b() {} // m.cppm export module m; export import :partA; export import :partB; // onlyUseB; export module onlyUseB; import m; export inline void onluUseB() { b(); } ``` the BMI of `onlyUseB` will change after we change the implementation of `partA.cppm` to `partA.v1.cppm`. Since `partA.v1.cppm` introduces new identifiers and types (the function prototype). So in this patch, we have to write the tests as: ``` // partA.cppm export module m:partA; export int getA() { ... } export int getA2(int) { ... } // partA.v1.cppm export module m:partA; export int getA() { ... } export int getA(int) { ... } export int getA2(int) { ... } // partB.cppm export module m:partB; export void b() {} // m.cppm export module m; export import :partA; export import :partB; // onlyUseB; export module onlyUseB; import m; export inline void onluUseB() { b(); } ``` so that the new introduced declaration `int getA(int)` doesn't introduce new identifiers and types, then the BMI of `onlyUseB` can keep unchanged. While it looks not so great, the patch should be the base of the patch to erase the transitive change for identifiers and types since I don't know how can we introduce new types and identifiers without introducing new declarations. Given how tightly the relationship between declarations, types and identifiers, I think we can only reach the ideal state after we made the series for all of the three entties. The design of the patch is similar to https://github.com/llvm/llvm-project/pull/86912, which extends the 32-bit DeclID to 64-bit and use the higher bits to store the module file index and the lower bits to store the Local Decl ID. A slight difference is that we only use 48 bits to store the new DeclID since we try to use the higher 16 bits to store the module ID in the prefix of Decl class. Previously, we use 32 bits to store the module ID and 32 bits to store the DeclID. I don't want to allocate additional space so I tried to make the additional space the same as 64 bits. An potential interesting thing here is about the relationship between the module ID and the module file index. I feel we can get the module file index by the module ID. But I didn't prove it or implement it. Since I want to make the patch itself as small as possible. We can make it in the future if we want. Another change in the patch is the new concept Decl Index, which means the index of the very big array `DeclsLoaded` in ASTReader. Previously, the index of a loaded declaration is simply the Decl ID minus PREDEFINED_DECL_NUMs. So there are some places they got used ambiguously. But this patch tried to split these two concepts. As https://github.com/llvm/llvm-project/pull/86912 did, the change will increase the on-disk PCM file sizes. As the declaration ID may be the most IDs in the PCM file, this can have the biggest impact on the size. In my experiments, this change will bring 6.6% increase of the on-disk PCM size. No compile-time performance regression observed. Given the benefits in the motivation example, I think the cost is worthwhile.
2024-04-25[NFC] [Serialization] Avoid using DeclID directly as much as possibleChuanqi Xu1-29/+38
This patch tries to remove all the direct use of DeclID except the real low level reading and writing. All the use of DeclID is converted to the use of LocalDeclID or GlobalDeclID. This is helpful to increase the readability and type safety.
2024-04-25Revert "[NFC] [Serialization] Avoid using DeclID directly as much as possible"Chuanqi Xu1-38/+29
This reverts commit 42070a5c092ed420bf92ebf38229c594885e94c7. I forgot to touch lldb.