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.
The 'routine' construct has two forms, one which takes the name of a
function that it applies to, and another where it implicitly figures it
out based on the next declaration. This patch implements the former with
the required restrictions on the name and the function-static-variables
as specified.
What has not been implemented is any clauses for this, any of the A.3.4
warnings, or the other form.
This patch makes it so the correct instantiation context is printed for
diagnostics suppessed by template argument deduction.
The context is saved along with the suppressed diagnostic, and when the
declaration they were attached to becomes used, we print the correct
context, instead of whatever context was at this point.
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
When substituting for rewrite purposes, as in rebuilding constraints for
a synthesized deduction guide, it assumed that packs were in
PackExpansion* form, such that the instantiator could extract a pattern.
For type aliases CTAD, while rebuilding their associated constraints,
this might not be the case because we'll call
`TransformTemplateArgument()` for the alias template arguments, where
there might be cases e.g. a non-pack expansion type into a pack
expansion, so the assumption wouldn't hold.
This patch fixes that by making it treat the non-pack expansions as
direct patterns when rewriting.
Fixes#124715
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>
Literal migration would result in dyn_cast_if_present (see the
definition of PointerUnion::dyn_cast), but this patch uses dyn_cast
because we expect Specialized to be nonnull. Note that if Specialized
were
null, dereferencing Tmpl would trigger a segfault.
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>
Literal migration would result in dyn_cast_if_present (see the
definition of PointerUnion::dyn_cast), but this patch uses dyn_cast
because we expect *Found to be nonnull. Note that if *Found were
null, cast<VarDecl>(TransformedDecl) would trigger an assertion error.
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>
This fixes instantiation of definition for friend function templates,
when the declaration found and the one containing the definition have
different template contexts.
In these cases, the the function declaration corresponding to the
definition is not available; it may not even be instantiated at all.
So this patch adds a bit which tracks which function template
declaration was instantiated from the member template. It's used to find
which primary template serves as a context for the purpose of
obtainining the template arguments needed to instantiate the definition.
Fixes#55509
Relanding patch, with no changes, after it was reverted due to revert of
commit this patch depended on.
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).
We used to always transform the pattern declaration for SizeOfPackExpr
to ensure the constraint expression's profile produced the desired
result. However, this approach failed to handle pack expansions when the
pack referred to function parameters. In such cases, the function
parameters were formerly expanded to 1 to avoid building Subst* nodes
(see e6974daa7). That workaround caused us to transform a pack without a
proper ArgumentPackSubstitutionIndex, leading to crashes when
transforming the pattern.
It turns out that profiling the pattern for partially substituted
SizeOfPackExprs is unnecessary because their transformed forms are also
profiled within the partial arguments.
Fixes https://github.com/llvm/llvm-project/issues/124161
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.
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>
Literal migration would result in dyn_cast_if_present (see the
definition of PointerUnion::dyn_cast), but this patch uses dyn_cast
because we expect Stored to be nonnull.
This patch partially implements CWG2369 for non-lambda-constrained
functions.
Lambdas are left intact at this point because we need extra work to
correctly instantiate captures before the function instantiation.
As a premise of CWG2369, this patch also implements CWG2770 to ensure
the function parameters are instantiated on demand.
Closes https://github.com/llvm/llvm-project/issues/54440
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.
The function definition instantiation assumes any declarations used
inside are already transformed before transforming the body, so we need
to preserve the transformed expression of CXXAssumeAttr even if it is
not a constant expression. Moreover, the full expression of the
assumption should also entail a potential lambda capture transformation,
hence the call to ActOnFinishFullExpr() after TransformExpr().
Fixes#114787
In 463a4f150, we assumed that all the template argument packs are of
size 1 when normalizing a constraint expression because I mistakenly
thought those packs were obtained from their injected template
parameters. This was wrong because we might be checking constraints when
instantiating a friend declaration within a class template
specialization, where the parent class template is specialized with
non-dependent template arguments.
In that sense, we shouldn't assume any pack size nor expand anything in
such a scenario. Moreover, there are no intermediate (substituted but
unexpanded) AST nodes for template template parameters, so we have to
special-case their transformations by looking into the instantiation
scope instead of extracting anything from template arguments.
Fixes#115098
In 50e5411e4, we preserved the pack substitution index within
SubstTemplateTypeParmType nodes and performed in-place expansions of
packs such that type constraints on a lambda that serve as a pattern of
a fold expression could be evaluated if the type constraints contain any
packs that are expanded by the fold expression.
However, we made an incorrect assumption of the condition under which
in-place expansion should occur. For example, a SizeOfPackExpr case
relies on SubstTemplateTypeParmType nodes being transformed to
SubstTemplateTypeParmPackTypes rather than expanding them immediately in
place.
This fixes that by adding a flag to SubstTemplateTypeParmType to
discriminate such in-place expansion situations.
Fixes https://github.com/llvm/llvm-project/issues/113518
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.
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
```
Consider the following:
```
template<typename T>
struct A {
template<typename U>
struct B {
static constexpr int x = 0; // #1
};
template<typename U>
struct B<U*> {
static constexpr int x = 1; // #2
};
};
template<>
template<typename U>
struct A<long>::B {
static constexpr int x = 2; // #3
};
static_assert(A<short>::B<int>::y == 0); // uses #1
static_assert(A<short>::B<int*>::y == 1); // uses #2
static_assert(A<long>::B<int>::y == 2); // uses #3
static_assert(A<long>::B<int*>::y == 2); // uses #3
```
According to [temp.spec.partial.member] p2:
> If the primary member template is explicitly specialized for a given
(implicit) specialization of the enclosing class template, the partial
specializations of the member template are ignored for this
specialization of the enclosing class template.
If a partial specialization of the member template is explicitly
specialized for a given (implicit) specialization of the enclosing class
template, the primary member template and its other partial
specializations are still considered for this specialization of the
enclosing class template.
The example above fails to compile because we currently don't implement
[temp.spec.partial.member] p2. This patch implements the wording, fixing #51051.
Currently, we store injected template arguments in
`RedeclarableTemplateDecl::CommonBase`. This approach has a couple
problems:
1. We can only access the injected template arguments of
`RedeclarableTemplateDecl` derived types, but other `Decl` kinds still
make use of the injected arguments (e.g.
`ClassTemplatePartialSpecializationDecl`,
`VarTemplatePartialSpecializationDecl`, and `TemplateTemplateParmDecl`).
2. Accessing the injected template arguments requires the common data
structure to be allocated. This may occur before we determine whether a
previous declaration exists (e.g. when comparing constraints), so if the
template _is_ a redeclaration, we end up discarding the common data
structure.
This patch moves the storage and access of injected template arguments
from `RedeclarableTemplateDecl` to `TemplateParameterList`.
This fixes layering violation introduced in
2fd01d75a863184766ee0c82b5c0fc8be172448a. The declaration is moved to
`SemaTemplateInstantiate` section of `Sema.h`, after the file where it's
implemented.
After #111852 refactored multi-level template argument list collection,
the following results in a crash:
```
template<typename T, bool B>
struct A;
template<bool B>
struct A<int, B>
{
void f() requires B;
};
template<bool B>
void A<int, B>::f() requires B { } // crash here
```
This happens because when collecting template arguments for constraint
normalization from a partial specialization, we incorrectly use the
template argument list of the partial specialization. We should be using
the template argument list of the _template-head_ (as defined in
[temp.arg.general] p2). Fixes#112222.
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.
Consider #109148:
```c++
template <typename ...Ts>
void f() {
[] {
(^Ts);
};
}
```
When we encounter `^Ts`, we try to parse a block and subsequently call
`DiagnoseUnexpandedParameterPack()` (in `ActOnBlockArguments()`), which
sees `Ts` and sets `ContainsUnexpandedParameterPack` to `true` in the
`LambdaScopeInfo` of the enclosing lambda. However, the entire block is
subsequently discarded entirely because it isn’t even syntactically
well-formed. As a result, `ContainsUnexpandedParameterPack` is `true`
despite the lambda’s body no longer containing any unexpanded packs,
which causes an assertion the next time
`DiagnoseUnexpandedParameterPack()` is called.
This pr moves handling of unexpanded parameter packs into
`CapturingScopeInfo` instead so that the same logic is used for both
blocks and lambdas. This fixes this issue since the
`ContainsUnexpandedParameterPack` flag is now part of the block (and
before that, its `CapturingScopeInfo`) and no longer affects the
surrounding lambda directly when the block is parsed. Moreover, this
change makes blocks actually usable with pack expansion.
This fixes#109148.
By allowing AnnotateAttr to be applied to statements, users can place arbitrary information in the AST for later use.
For example, this can be used for HW-targeted language extensions that involve specialized loop annotations.
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 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.
This fixes instantiation of definition for friend function templates,
when the declaration found and the one containing the definition
have different template contexts.
In these cases, the the function declaration corresponding to the
definition is not available; it may not even be instantiated at all.
So this patch adds a bit which tracks which function template
declaration was instantiated from the member template.
It's used to find which primary template serves as a context
for the purpose of obtaining the template arguments needed
to instantiate the definition.
Fixes#55509
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.
When instantiating a class template, we would lose track of function
template explicit specializations, marking them with the wrong
specialization kind.
This would lead to improperly using the explcit specialization arguments
to instantiate the function body.
This also better matches MSVC on the behaviour of explicitly vs
implicitly instantiating these.
Fixes#111266
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 things.
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.