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
Add `NamespaceBaseDecl` as common base class of `NamespaceDecl` and
`NamespaceAliasDecl`. This simplifies `NestedNameSpecifier` a bit.
Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
ASTContext::getDefaultCallingConvention() was documented as returning
"the default calling convention for the current target", but did not do
this, and was never intended to do this, it has always been controlled
by command-line options to deviate from the target default.
This commit changes ASTContext::getDefaultCallingConvention() to reflect
the fact that it returns the context's default calling convention, not
the target's default calling convention. The IsBuiltin parameter, which
was used to return the target's default calling convention rather than
the context's, is removed in favor of
getTargetInfo().getDefaultCallingConv() which is more explicit of the
intent.
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 relands https://github.com/llvm/llvm-project/pull/135119, after
fixing crashes seen in LLDB CI reported here:
https://github.com/llvm/llvm-project/pull/135119#issuecomment-2794910840
Fixes https://github.com/llvm/llvm-project/pull/135119
This changes the TemplateArgument representation to hold a flag
indicating whether a tempalte argument of expression type is supposed to
be canonical or not.
This gets one step closer to solving
https://github.com/llvm/llvm-project/issues/92292
This still doesn't try to unique as-written TSTs. While this would
increase the amount of memory savings and make code dealing with the AST
more well-behaved, profiling template argument lists is still too
expensive for this to be worthwhile, at least for now.
This also fixes the context creation of TSTs, so that they don't in some
cases get incorrectly flagged as sugar over their own canonical form.
This is captured in the test expectation change of some AST dumps.
This fixes some places which were unnecessarily canonicalizing these
TSTs.
This changes the TemplateArgument representation to hold a flag
indicating whether a template argument of expression type is supposed to
be canonical or not.
This gets one step closer to solving
https://github.com/llvm/llvm-project/issues/92292
This still doesn't try to unique as-written TSTs. While this would
increase the amount of memory savings and make code dealing with the AST
more well-behaved, profiling template argument lists is still too
expensive for this to be worthwhile, at least for now. Without this
uniquing, this patch stands neutral in terms of performance impact.
This also fixes the context creation of TSTs, so that they don't in some
cases get incorrectly flagged as sugar over their own canonical form.
This is captured in the test expectation change of some AST dumps.
This fixes some places which were unnecessarily canonicalizing these
TSTs.
Instead of manually adding a note pointing to the relevant template
parameter to every relevant error, which is very easy to miss, this
patch adds a new instantiation context note, so that this can work using
RAII magic.
This fixes a bunch of places where these notes were missing, and is more
future-proof.
Some diagnostics are reworked to make better use of this note:
- Errors about missing template arguments now refer to the parameter
which is missing an argument.
- Template Template parameter mismatches now refer to template
parameters as parameters instead of arguments.
It's likely this will add the note to some diagnostics where the
parameter is not super relevant, but this can be reworked with time and
the decrease in maintenance burden makes up for it.
This bypasses the templight dumper for the new context entry, as the
tests are very hard to update.
This depends on #125453, which is needed to avoid losing the context
note for errors occuring during template argument deduction.
This makes it significantly easier to add new builtin templates, since
you only have to modify two places instead of a dozen or so.
The `BuiltinTemplates.td` could also be extended to generate
documentation from it in the future.
This fixes the core issue described in P3579, following the design
intent of P0522 to not introduce any new cases where a template template
parameter match is allowed for a template which is not valid for all
possible uses.
With this patch, narrowing conversions are disallowed for TTP matching.
This reuses the existing machinery for diagnosing narrowing in a
converted constant expression.
Since P0522 is a DR and we apply it all the way back to C++98, this
brings that machinery to use in older standards, in this very narrow
scope of TTP matching.
This still doesn't solve the ambiguity when partial ordering NTTPs of
different integral types, this is blocked by a different bug which will
be fixed in a subsequent patch (but the test cases are added).
Close https://github.com/llvm/llvm-project/issues/123815
See the comments for details. We can't get primary context arbitrarily
since the redecl may have different context and information.
There is a TODO for modules specific case, I'd like to make it after
this PR.
This patch relands the following PRs:
* #111711
* #107350
* #111457
All of these patches were reverted due to an issue reported in
https://github.com/llvm/llvm-project/pull/111711#issuecomment-2406491485,
due to interdependencies.
---
[clang] Finish implementation of P0522
This finishes the clang implementation of P0522, getting rid
of the fallback to the old, pre-P0522 rules.
Before this patch, when partial ordering template template parameters,
we would perform, in order:
* If the old rules would match, we would accept it. Otherwise, don't
generate diagnostics yet.
* If the new rules would match, just accept it. Otherwise, don't
generate any diagnostics yet again.
* Apply the old rules again, this time with diagnostics.
This situation was far from ideal, as we would sometimes:
* Accept some things we shouldn't.
* Reject some things we shouldn't.
* Only diagnose rejection in terms of the old rules.
With this patch, we apply the P0522 rules throughout.
This needed to extend template argument deduction in order
to accept the historial rule for TTP matching pack parameter to non-pack
arguments.
This change also makes us accept some combinations of historical and P0522
allowances we wouldn't before.
It also fixes a bunch of bugs that were documented in the test suite,
which I am not sure there are issues already created for them.
This causes a lot of changes to the way these failures are diagnosed,
with related test suite churn.
The problem here is that the old rules were very simple and
non-recursive, making it easy to provide customized diagnostics,
and to keep them consistent with each other.
The new rules are a lot more complex and rely on template argument
deduction, substitutions, and they are recursive.
The approach taken here is to mostly rely on existing diagnostics,
and create a new instantiation context that keeps track of this context.
So for example when a substitution failure occurs, we use the error
produced there unmodified, and just attach notes to it explaining
that it occurred in the context of partial ordering this template
argument against that template parameter.
This diverges from the old diagnostics, which would lead with an
error pointing to the template argument, explain the problem
in subsequent notes, and produce a final note pointing to the parameter.
---
[clang] CWG2398: improve overload resolution backwards compat
With this change, we discriminate if the primary template and which partial
specializations would have participated in overload resolution prior to
P0522 changes.
We collect those in an initial set. If this set is not empty, or the
primary template would have matched, we proceed with this set as the
candidates for overload resolution.
Otherwise, we build a new overload set with everything else, and proceed
as usual.
---
[clang] Implement TTP 'reversed' pack matching for deduced function template calls.
Clang previously missed implementing P0522 pack matching
for deduced function template calls.
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)
With this change, we discriminate if the primary template and which
partial specializations would have participated in overload resolution
prior to P0522 changes.
We collect those in an initial set. If this set is not empty, or the
primary template would have matched, we proceed with this set as the
candidates for overload resolution.
Otherwise, we build a new overload set with everything else, and proceed
as usual.
This implements the logic of the `common_type` base template as a
builtin alias. If there should be no `type` member, an empty class is
returned. Otherwise a specialization of a `type_identity`-like class is
returned. The base template (i.e. `std::common_type`) as well as the
empty class and `type_identity`-like struct are given as arguments to
the builtin.
We were incorrectly not deduplicating results when looking up `_` which,
for a lambda init capture, would result in an ambiguous lookup.
The same bug caused some diagnostic notes to be emitted twice.
Fixes#107024
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.
WG14 N3274 removed _Imaginary from Annex G. Clang has never fully
supported Annex G or _Imaginary, so removal is pretty trivial for us.
Note, we are keeping _Imaginary as a keyword so that we get better
diagnostic behavior. This is still conforming because _I makes it a
reserved identifier, so it's not available for users to use as an
identifier anyway.
This patch moves documentation of `Sema` functions from `.cpp` files to `Sema.h` when there was no documentation in the latter, or it can be trivially subsumed. More complicated cases when there's less trivial divergence between documentation attached to declaration and the one attached to implementation are left for a later PR that would require review.
It appears that doxygen can find the documentation for a function defined out-of-line even if it's attached to an implementation, and not declaration. But other tools, e.g. clangd, are not as powerful. So this patch significantly improves autocompletion experience for (at least) clangd-based IDEs.
module
Possibly fix https://github.com/llvm/llvm-project/issues/96693
The direct reason is that we are calculating the linkage for the
declaration too early so that the linkage got calculated incorrectly.
And after I look into the problem, I found it is completely not
necessary to calculate the linkage there. It is for ModulesTS. So I
simply removes that legacy experimental code and fix the issue.
This patch extracts the logci to decide how we decide the module units
belongs to the same module into a member function of ASTContext. This is
helpful to refactor the implementation in the future.
This patch moves `Sema` functions that are specific for RISC-V into the
new `SemaRISCV` class. This continues previous efforts to split `Sema`
up. Additional context can be found in
https://github.com/llvm/llvm-project/pull/84184.
This PR is somewhat different from previous PRs on this topic:
1. Splitting out target-specific functions wasn't previously discussed.
It felt quite natural to do, though.
2. I had to make some static function in `SemaChecking.cpp` member
functions of `Sema` in order to use them in `SemaRISCV`.
3. I dropped "RISCV" from identifiers, but decided to leave "RVV"
(RISC-V "V" vector extensions) intact. I think it's an idiomatic
abbreviation at this point, but I'm open to input from contributors in
that area.
4. I repurposed `SemaRISCVVectorLookup.cpp` for `SemaRISCV`.
I think this was a successful experiment, which both helps the goal of
splitting `Sema` up, and shows a way to approach `SemaChecking.cpp`,
which I wasn't sure how to approach before. As we move more
target-specific function out of there, we'll gradually make the checking
"framework" inside `SemaChecking.cpp` public, which is currently a whole
bunch of static functions. This would enable us to move more functions
outside of `SemaChecking.cpp`.
According to [expr.prim.id.general] p2:
> If an _id-expression_ `E` denotes a non-static non-type member of some
class `C` at a point where the current class is `X` and
> - `E` is potentially evaluated or `C` is `X` or a base class of `X`,
and
> - `E` is not the _id-expression_ of a class member access expression,
and
> - if `E` is a _qualified-id_, `E` is not the un-parenthesized operand
of the unary `&` operator,
>
> the _id-expression_ is transformed into a class member access
expression using `(*this)` as the object expression.
Consider the following:
```
struct A
{
void f0();
template<typename T>
void f1();
};
template<typename T>
struct B : T
{
auto g0() -> decltype(T::f0()); // ok
auto g1() -> decltype(T::template f1<int>()); // error: call to non-static member function without an object argument
};
template struct B<A>;
```
Clang incorrectly rejects the call to `f1` in the _trailing-return-type_
of `g1`. Furthermore, the following snippet results in a crash during
codegen:
```
struct A
{
void f();
};
template<typename T>
struct B : T
{
template<typename U>
static void g();
template<>
void g<int>()
{
return T::f(); // crash here
}
};
template struct B<A>;
```
This happens because we unconditionally build a
`CXXDependentScopeMemberExpr` (with an implicit object expression) for
`T::f` when parsing the template definition, even though we don't know
whether `g` is an implicit object member function yet.
This patch fixes these issues by instead building
`DependentScopeDeclRefExpr`s for such expressions, and only transforming
them into implicit class member access expressions during instantiation.
Since we implemented the MS "unqualified lookup into dependent bases"
extension by building an implicit class member access (and relying on
the first component name of the _nested-name-specifier_ to be looked up
in the context of the object expression during instantiation), we
instead pre-append a fake _nested-name-specifier_ that refers to the
injected-class-name of the enclosing class. This patch also refactors
`Sema::BuildQualifiedDeclarationNameExpr` and
`Sema::BuildQualifiedTemplateIdExpr`, streamlining their implementation
and removing any redundant checks.