The import and include problem is a long-standing issue with the use of
C++20 modules. This patch tried to improve this by skipping parsing
class and functions if their declaration is already defined in modules.
The scale of the patch itself is small as the patch reuses previous
optimization. Maybe we can skip parsing other declarations in the
future. But the patch itself should be good.
For the common pattern:
```C++
module;
export module a;
...
```
```C++
// a.cpp
import a;
```
In this case, we're already able to skip parsing the body of some
declarations in a.cpp. Add a test to show the ability.
In C++, it can be assumed the same linkage will be computed for all
redeclarations of an entity, and we have assertions to check this.
However, the linkage for a declaration can be requested in the middle of
deserealization, and at this point the redecl chain is not well formed,
as computation of the most recent declaration is deferred.
This patch makes that assertion work even in such conditions.
This fixes a regression introduced in
https://github.com/llvm/llvm-project/pull/147835, which was never
released, so there are no release notes for this.
Fixes#153933
Close https://github.com/llvm/llvm-project/issues/138558
The compiler failed to understand the redeclaration-relationship when
performing checks when MergeFunctionDecl. This seemed to be a complex
circular problem (how can we know the redeclaration relationship before
performing merging?). But the fix seems to be easy and safe. It is fine
to only perform the check only if the using decl is a local decl.
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
Several Clang tests were failing on Cygwin, and were already marked as
requiring !system-windows, unsupported on system-windows, or xfail on
system-windows. Add system-cygwin to lit's llvm.config, and use it in
such tests in addition to system-windows.
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
On COFF platform, d1b0cbff806b50d399826e79b9a53e4726c21302 generates a
debug info linked with VTable regardless definition is present or not.
If that VTable ends up implicitly dllimported from another DLL, ld.bfd
produces a runtime pseudo relocation for it (LLD doesn't, since
d17db6066d2524856fab493dd894f8396e896bc7). If the debug section is
stripped, the runtime pseudo relocation points to memory space outside
of the module, causing an access violation.
At this moment, we simply disable VTable debug info on COFF platform to
avoid this problem.
This is still crashing on AIX and Solaris. It looks like maybe issues
due to trying to delete the current working directory. cd to the source
directory beforehand to try and work around that.
When the static analyzer is disabled with
-DCLANG_ENABLE_STATIC_ANALYZER=OFF, the newly added
specializations-lazy-load-parentmap-crash.cpp test fails with:
error: action RunAnalysis not compiled in
--
********************
********************
Failed Tests (1):
Clang :: Modules/specializations-lazy-load-parentmap-crash.cpp
Split out the part of the test that requires the static analyzer so that
it does not run when the static analyzer is unavailable.
This patch removes %T from clang lit tests. %T has been deprecated for
about seven years and is not reccomended as it is not unique to each
test, which can lead to races. This patch is intended to remove usage in
tree with the end goal of removing support for %T within lit.
## 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()`.
Tracked at https://github.com/llvm/llvm-project/issues/112294
This patch implements from [basic.link]p14 to [basic.link]p18 partially.
The explicitly missing parts are:
- Anything related to specializations.
- Decide if a pointer is associated with a TU-local value at compile
time.
- [basic.link]p15.1.2 to decide if a type is TU-local.
- Diagnose if TU-local functions from other TU are collected to the
overload set. See [basic.link]p19, the call to 'h(N::A{});' in
translation unit #2
There should be other implicitly missing parts as the wording uses
"names" briefly several times. But to implement this precisely, we have
to visit the whole AST, including Decls, Expression and Types, which may
be harder to implement and be more time-consuming for compilation time.
So I choose to implement the common parts.
It won't be too bad to miss some cases since we DIDN'T do any such
checks in the past 3 years. Any new check is an improvement. Given
modules have been basically available since clang15 without such checks,
it will be user unfriendly if we give a hard error now. And there are
a lot of cases which violating the rule actually just fine. So I decide
to emit it as warnings instead of hard errors.
As documented in 20.x, we'd like to keep reduced BMI off by default for
1~2 versions. And now we're in 22.x.
I rarely receive bug reports for reduced BMI. I am not sure about the
reason. Maybe not a lot of people are using it. Or it is really stable
enough.
And also, we've been enabling the reduced BMI internally for roughly half a
year.
So I think it's the time to move on. See the document changes for other
information.
Change the error message from "export declaration can only be used
within a module purview" to "export declaration can only be used within
a module interface" to be technically accurate.
The previous message was misleading because export declarations are
actually within a module purview when used in module implementation
units, but they are only allowed in module interface units.
This addresses the issue pointed out in GitHub issue #149008 where
Bigcheese noted that the diagnostic wording was incorrect.
Fixes#149008
EvaluateAsInitializer does not support evaluating values with dependent
types. This was previously guarded with a check for the initializer
expression, but it is possible for the VarDecl to have a dependent type
without the initializer having a dependent type, when the initializer is
a specialized template type and the VarDecl has the unspecialized type.
This adds a guard checking for dependence in the VarDecl type as well.
This fixes the issue raised by Google in
https://github.com/llvm/llvm-project/pull/145447
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
This fixes an issue with the ODR checker not using the as-written type
of conversion operators.
The odr-checker in general should not have to deal with canonical types,
as its purpose is to compare same definitions across TUs, and these need
to be same as written, with few exceptions.
Using canonical types is specially problematic when expressions are
involved, as the types which refer to them generally pick an arbitrary
representative expression, and this can lead to false mismatches.
This patch makes sure that when hashing the names of declarations, if a
DeclarationNameInfo is available, its type source info is used, instead
of the type contained in the DeclarationName, which otherwise is always
canonical.
This patch supersedes #144796, as it fixes the problem without weakening
the ODR checker.
Fixes https://github.com/llvm/llvm-project/issues/143152
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.
It looks an overlook that debug info can't play well with
explicit template instantiation. Tested in donwstream for years. I just
forgot to upstream it.
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 PR is 2nd part of
[P1857R3](https://github.com/llvm/llvm-project/pull/107168)
implementation, and mainly implement the restriction `A module directive
may only appear as the first preprocessing tokens in a file (excluding
the global module fragment.)`:
[cpp.pre](https://eel.is/c++draft/cpp.pre):
```
module-file:
pp-global-module-fragment[opt] pp-module group[opt] pp-private-module-fragment[opt]
```
We also refine tests use `split-file` instead of conditional macro.
Signed-off-by: yronglin <yronglin777@gmail.com>
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 test relies on two modules being different sizes, which is not always true
with different architectures. Make the test x86 specific at the moment to
ensure it does not fail spuriously.
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.
WG14 N3469 changed _Lengthof to _Countof but it also introduced the
<stdcountof.h> header to expose a macro with a non-ugly identifier. GCC
vends this header as part of the compiler implementation, so Clang
should do the same.
Suggested-by: Alejandro Colomar <alx@kernel.org>
The IR now includes a global variable for the debugger that holds
the address of the vtable.
Now every class that contains virtual functions, has a static
member (marked as artificial) that identifies where that vtable
is loaded in memory. The unmangled name is '_vtable$'.
This new symbol will allow a debugger to easily associate
classes with the physical location of their VTables using
only the DWARF information. Previously, this had to be done
by searching for ELF symbols with matching names; something
that was time-consuming and error-prone in certain edge cases.
Recently in some of our internal testing, we noticed that the compiler
was sometimes generating an empty linker.options section which seems
unnecessary. This proposed change causes the compiler to simply omit
emitting the linker.options section if it is empty.
This test started failing after 7a242387: https://lab.llvm.org/buildbot/#/builders/154/builds/16276. There seem to be two bugs:
* The `-fno-modules-force-validate-user-headers` flag was passed on the wrong line.
* Changing source files was being done without an explicit `sleep`, meaning there was a possibility of the files maintaining their old modification time and not triggering the expected rebuilds.