This is a major change on how we represent nested name qualifications in
the AST.
* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.
This patch offers a great performance benefit.
It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.
This has great results on compile-time-tracker as well:

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.
It has some other miscelaneous drive-by fixes.
About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.
There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.
How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.
The rest and bulk of the changes are mostly consequences of the changes
in API.
PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.
Fixes#136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
When two threads are accessing the same `pcm`, it is possible that the
reading thread sees the timestamp update, while the file on disk is not
updated.
This PR moves timestamp update from `writeAST` to
`compileModuleAndReadASTImpl`, so we only update the timestamp after the
file has been committed to disk.
rdar://152097193
This patch adds the 'init recipes' to firstprivate like I did for
'private', so that we can properly init these types. At the moment,
the recipe init isn't generated (just the VarDecl), and this isn't
really used anywhere as it will be used exclusively in Codegen.
Previously, #151360 implemented 'private' clause lowering, but didn't
properly initialize the variables. This patch adds that behavior to make
sure we correctly get the constructor or other init called.
This fixes an ambiguous type type_info when you try and reference the
`type_info` type while using clang modulemaps with `-fms-compatibility`
enabled
Fixes#38400
This is a first pass at implementing
[P2841R7](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2841r7.pdf).
The implementation is far from complete; however, I'm aiming to do that
in chunks, to make our lives easier.
In particular, this does not implement
- Subsumption
- Mangling
- Satisfaction checking is minimal as we should focus on #141776 first
(note that I'm currently very stuck)
FTM, release notes, status page, etc, will be updated once the feature
is more mature. Given the state of the feature, it is not yet allowed in
older language modes.
Of note:
- Mismatches between template template arguments and template template
parameters are a bit wonky. This is addressed by #130603
- We use `UnresolvedLookupExpr` to model template-id. While this is
pre-existing, I have been wondering if we want to introduce a different
OverloadExpr subclass for that. I did not make the change in this patch.
Previously, the `sycl_kernel_entry_point` attribute could be specified
using either the GNU or C++11 spelling styles. Future SYCL attributes
are expected to support only the C++11 spelling style, so support for
the GNU style is being removed.
In order to ensure consistent presentation of the attribute in
diagnostic messages, diagnostics specific to this attribute now require
the attribute to be provided as an argument. This delegates formatting
of the attribute name to the diagnostic engine.
As an additional nicety, "the" is added to some diagnostic messages so
that they read more like proper sentences.
Handles clang::DiagnosticsEngine and clang::DiagnosticIDs.
For DiagnosticIDs, this mostly migrates from `new DiagnosticIDs` to
convenience method `DiagnosticIDs::create()`.
Part of cleanup https://github.com/llvm/llvm-project/issues/151026
## Problem
This is a regression that was observed in Clang 20 on modules code that
uses import std.
The lazy-loading mechanism for template specializations introduced in
#119333 can currently load additional nodes when called multiple times,
which breaks assumptions made by code that iterates over
specializations. This leads to iterator invalidation crashes in some
scenarios.
The core issue occurs when:
1. Code calls `spec_begin()` to get an iterator over template
specializations. This invokes `LoadLazySpecializations()`.
2. Code then calls `spec_end()` to get the end iterator.
3. During the `spec_end()` call, `LoadExternalSpecializations()` is
invoked again.
4. This can load additional specializations for certain cases,
invalidating the begin iterator returned in 1.
I was able to trigger the problem when constructing a ParentMapContext.
The regression test demonstrates two ways to trigger the construction of
the ParentMapContext on problematic code:
- The ArrayBoundV2 checker
- Unsigned overflow detection in sanitized builds
Unfortunately, simply dumping the ast (e.g. using `-ast-dump-all`)
doesn't trigger the crash because dumping requires completing the redecl
chain before iterating over the specializations.
## Solution
The fix ensures that the redeclaration chain is always completed
**before** loading external specializations by calling
`CompleteRedeclChain(D)` at the start of
`LoadExternalSpecializations()`. The idea is to ensure that all
`SpecLookups` are fully known and loaded before the call to
`LoadExternalSpecializationsImpl()`.
The checks for the 'z' and 't' format specifiers added in the original
PR #143653 had some issues and were overly strict, causing some build
failures and were consequently reverted at
4c85bf2fe8.
In the latest commit
27c58629ec,
I relaxed the checks for the 'z' and 't' format specifiers, so warnings
are now only issued when they are used with mismatched types.
The original intent of these checks was to diagnose code that assumes
the underlying type of `size_t` is `unsigned` or `unsigned long`, for
example:
```c
printf("%zu", 1ul); // Not portable, but not an error when size_t is unsigned long
```
However, it produced a significant number of false positives. This was
partly because Clang does not treat the `typedef` `size_t` and
`__size_t` as having a common "sugar" type, and partly because a large
amount of existing code either assumes `unsigned` (or `unsigned long`)
is `size_t`, or they define the equivalent of size_t in their own way
(such as
sanitizer_internal_defs.h).2e67dcfdcd/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h (L203)
Including the results of `sizeof`, `sizeof...`, `__datasizeof`,
`__alignof`, `_Alignof`, `alignof`, `_Countof`, `size_t` literals, and
signed `size_t` literals, the results of pointer-pointer subtraction and
checks for standard library functions (and their calls).
The goal is to enable clang and downstream tools such as clangd and
clang-tidy to provide more portable hints and diagnostics.
The previous discussion can be found at #136542.
This PR implements this feature by introducing a new subtype of `Type`
called `PredefinedSugarType`, which was considered appropriate in
discussions. I tried to keep `PredefinedSugarType` simple enough yet not
limited to `size_t` and `ptrdiff_t` so that it can be used for other
purposes. `PredefinedSugarType` wraps a canonical `Type` and provides a
name, conceptually similar to a compiler internal `TypedefType` but
without depending on a `TypedefDecl` or a source file.
Additionally, checks for the `z` and `t` format specifiers in format
strings for `scanf` and `printf` were added. It will precisely match
expressions using `typedef`s or built-in expressions.
The affected tests indicates that it works very well.
Several code require that `SizeType` is canonical, so I kept `SizeType`
to its canonical form.
The failed tests in CI are allowed to fail. See the
[comment](https://github.com/llvm/llvm-project/pull/135386#issuecomment-3049426611)
in another PR #135386.
Add `NamespaceBaseDecl` as common base class of `NamespaceDecl` and
`NamespaceAliasDecl`. This simplifies `NestedNameSpecifier` a bit.
Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
Some `LangOptions` duplicate their `CodeGenOptions` counterparts. My
understanding is that this was done solely because some infrastructure
(like preprocessor initialization, serialization, module compatibility
checks, etc.) were only possible/convenient for `LangOptions`. This PR
implements the missing support for `CodeGenOptions`, which makes it
possible to remove some duplicate `LangOptions` fields and simplify the
logic. Motivated by https://github.com/llvm/llvm-project/pull/146342.
C++23 mandates that temporaries used in range-based for loops are
lifetime-extended
to cover the full loop. This patch adds a check for loop variables and
compiler-
generated `__range` bindings to apply the correct extension.
Includes test cases based on examples from CWG900/P2644R1.
Fixes https://github.com/llvm/llvm-project/issues/109793
This removes the `{BENIGN,COMPATIBLE}{,_ENUM,_VALUE}_LANGOPT` X macros
controlling `LangOptions`. These are permutations of the base `LANGOPT`,
`ENUM_LANGOPT` and `VALUE_LANGOPT` X macros that also carry the
information of their effect on AST (and therefore module compatibility).
Their functionality is now implemented by passing `Benign`, `Compatible`
or `NotCompatible` argument to the base X macros and using C++17 `if
constexpr` in the clients to achieve the same codegen.
This PR solves this FIXME:
```
// FIXME: Clients should be able to more easily select whether they want
// different levels of compatibility versus how to handle different kinds
// of option.
```
The base X macros are preserved, since they are used in `LangOptions.h`
to generate different kinds of field and function declarations for
flags, values and enums, which can't be achieved with `if constexpr`.
The new syntax also forces developers to think about compatibility when
adding new language option, hopefully reducing the number of new options
that are affecting by default even though they are benign or compatible.
Note that the `BENIGN_` macros used to forward to their `COMPATIBLE_`
counterparts. I don't think this ever kicked in, since there are no
clients of the `.def` file that define `COMPATIBLE_` without also
defining `BENIGN_`. However, this might be something downstream forks
need to take care of by doing `if constexpr (CK::Compatibility ==
CK::Benign || CK::Compatibility == CK::Compatible)` in place of `#define
COMPATIBLE_`.
All deserialized VarDecl initializers are EvaluatedStmt, but not all
EvaluatedStmt initializers are from a PCH. Calling
`VarDecl::hasInitWithSideEffects` can trigger constant evaluation, but
it's hard to know ahead of time whether that will trigger
deserialization - even if the initializer is fully deserialized, it may
contain a call to a constructor whose body is not deserialized. By
caching the result of `VarDecl::hasInitWithSideEffects` and populating
that cache during deserialization we can guarantee that calling it won't
trigger deserialization regardless of the state of the initializer.
This also reduces memory usage by removing the `InitSideEffectVars` set
in `ASTReader`.
rdar://154717930
See the attached test for the motiviation.
Previously we dependent on the module ownership of the decl context to
perform module local lookup. But if the lookup is unqualified, we may
perform the lookup with canonical decl, which belongs to the incorrect
named module
These are identified by misc-include-cleaner. I've filtered out those
that break builds. Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
ArrayRef(std::nullopt) just got deprecated. This patch does the same
to MutableArrayRef(std::nullopt). Since there are only a couple of
uses, this patch does migration and deprecation at the same time.
Introduce a type alias for the commonly used `std::pair<FileID,
unsigned>` to improve code readability, and make it easier for future
updates (64-bit source locations).
This is needed by no casacading chanegs feature. A BMI of a module
interface needs to merge the hash value of all the module files that
the users can touched actually.
See the discussion in https://github.com/llvm/llvm-project/pull/145529.
This will slightly increase the PCM size (~5%), some data (in-memory
preamble size in clangd):
- SemaExpr.cpp: 77MB -> 80MB
- FindTarget.cpp: 71MB -> 75MB
Implement parsing and semantic analysis support for the optional
'strict' modifier of the num_threads clause. This modifier has been
introduced in OpenMP 6.0, section 12.1.2.
Note: this is basically 1:1 https://reviews.llvm.org/D138328.
Reverts llvm/llvm-project#143739 because it triggers an assert:
```
Assertion failed: (!isNull() && "Cannot retrieve a NULL type pointer"), function getCommonPtr, file Type.h, line 952.
```
Calling `DeclMustBeEmitted` should not lead to more deserialization, as
it may occur before previous deserialization has finished.
When passed a `VarDecl` with an initializer however, `DeclMustBeEmitted`
needs to know whether that initializer contains side effects. When the
`VarDecl` is deserialized but the initializer is not, this triggers
deserialization of the initializer. To avoid this we add a bit to the
serialization format for `VarDecl`s, indicating whether its initializer
contains side effects or not, so that the `ASTReader` can query this
information directly without deserializing the initializer.
rdar://153085264
Close https://github.com/llvm/llvm-project/issues/131058
See the comments in
ASTWriter.cpp:ASTDeclContextNameLookupTrait::getLookupVisibility and
SemaLookup.cpp:Sema::makeMergedDefinitionVisible for details.
This patch is closely related to #139293 and addresses an existing issue
in the loop transformation codebase. Specifically, it corrects the
handling of the `NumGeneratedLoops` variable in
`OMPLoopTransformationDirective` AST nodes and its inheritors (such as
OMPUnrollDirective, OMPTileDirective, etc.).
Previously, this variable was inaccurately set for certain
transformations like reverse or tile. While this did not lead to
functional bugs, since the value was only checked to determine whether
it was greater than zero or equal to zero, the inconsistency could
introduce problems when supporting more complex directives in the
future.
Close https://github.com/llvm/llvm-project/issues/119947
As discussed in the above thread, we shouldn't write specializations
with local args in reduced BMI. Since users can't find such
specializations any way.
This patch reduces the size of several AST nodes by moving some fields
into the free bitfield space in the base `Stmt` class:
* `CXXForRangeStmt`: 96 → 88 bytes
* `ChooseExpr`: 56 → 48 bytes
* `ArrayTypeTraitExpr`: 56 → 48 bytes
* `ExpressionTraitExpr`: 40 → 32 bytes
* `CXXFoldExpr`: 64 → 56 bytes
* `ShuffleExpr`: 40 → 32 bytes
* `PackIndexingExpr`: 48 → 40 bytes
There are no noticeable memory savings (`Expr/Stmt` memory usage
125,824,496 vs 125,826,336 bytes for `SemaExpr.cpp`) in my testing,
likely because these node types are not among the most common in typical
ASTs.
This is a follow-up fix to
https://github.com/llvm/llvm-project/pull/109167.
Previously, we stored a mapping between the enclosing function and the
lambda class declaration. When loading the enclosing function, we also
loaded the corresponding lambda class declaration. However, loading the
lambda class declaration does not guarantee that its call operator (a
`CXXMethodDecl`) is loaded as well.
As a result, if the lambda call operator is later loaded from a
different module, we can end up with a `DeclRefExpr` that refers to a
`VarDecl` from a different module — leading to inconsistencies.
To fix this, we should ensure the lambda call operator itself is loaded.
Fixes#141582
This is a fix for a completely unrelated patch, that started to cause
failures in the explicit-build.cpp test because the size of the b.pcm
and b-not-a.pcm files became the same. The alignment added by empty
ObjCCategory blobs being written to the file causes them to become the
same size, and the error 'module file has a different size than
expected' will not be emitted as the pcms only track module size, not
content, for whether they are valid.
This prevents that issue by not saving the ObjCCategories if it is
empty. The change in clang/lib/Serialization/ASTReaderDecl.cpp is just
formatting, but shows that the only use of ObjCCategoriesMap loaded from
the file will be OK with null (never loaded) data. It is a bit of a weird
fix, but should help decrease the size of the modules for objects that
are not used.
These are identified by misc-include-cleaner. I've filtered out those
that break builds. Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.