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.
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)
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.
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.
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.
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.
(This continues the effort of #86265, fixing another piece of issue in
constraint evaluation on variadic lambdas.)
We need the depth of the primary template parameters for constraint
substitution. To that end, we avoided substituting type constraints by
copying the constraint expression when instantiating a template. This,
however, has left an issue in that for lambda's parameters, they can
reference outer template packs that would be expanded in the process of
an instantiation, where these parameters would make their way into the
constraint evaluation, wherein we have no other way to expand them later
in evaluation. For example,
template <class... Ts> void foo() {
bar([](C<Ts> auto value) {}...);
}
The lambda references a pack `Ts` that should be expanded when
instantiating `foo()`. The `Ts` along with the constraint expression
would not be transformed until constraint evaluation, and at that point,
we would have no chance to expand `Ts` anyhow.
This patch takes an approach that transforms `Ts` from an unexpanded
TemplateTypeParmType into a SubstTemplateTypeParmType with the current
pack substitution index, such that we could use that to expand the type
during evaluation.
Fixes#101754
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.
Currently, clang rejects the following explicit specialization of `f`
due to the constraints not being equivalent:
```
template<typename T>
struct A
{
template<bool B>
void f() requires B;
};
template<>
template<bool B>
void A<int>::f() requires B { }
```
This happens because, in most cases, we do not set the flag indicating
whether a `RedeclarableTemplate` is an explicit specialization of a
member of an implicitly instantiated class template specialization until
_after_ we compare constraints for equivalence. This patch addresses the
issue (and a number of other issues) by:
- storing the flag indicating whether a declaration is a member
specialization on a per declaration basis, and
- significantly refactoring `Sema::getTemplateInstantiationArgs` so we
collect the right set of template argument in all cases.
Many of our declaration matching & constraint evaluation woes can be
traced back to bugs in `Sema::getTemplateInstantiationArgs`. This
change/refactor should fix a lot of them. It also paves the way for
fixing #101330 and #105462 per my suggestion in #102267 (which I have
implemented on top of this patch but will merge in a subsequent PR).
When rebuilding immediate invocations inside
`RemoveNestedImmediateInvocation()`, we employed a `TreeTransform` to
exercise the traversal. The transformation has a side effect that, for
template specialization types, their default template arguments are
substituted separately, and if any lambdas are present, they will be
transformed into distinct types than those used to instantiate the
templates right before the `consteval` handling.
This resulted in `B::func()` getting redundantly instantiated for the
case in question. Since we're also in an immediate evaluation context,
the body of `foo()` would also get instantiated, so we end up with a
spurious friend redefinition error.
Like what we have done in `ComplexRemove`, this patch also avoids the
lambda's transformation in TemplateInstantiator if we know we're
rebuilding immediate calls. In addition, this patch also consolidates
the default argument substitution logic in
`CheckTemplateArgumentList()`.
Fixes#107175
Since #93433, we have switched to `QualifiedTemplateName`s in more
situations to preserve sugars in diagnostics. However, there is one
missed case in typo correction that might not meet the expectation in
`CheckDeductionGuideDeclarator()`.
Fixes https://github.com/llvm/llvm-project/issues/107887
This extends default argument deduction to cover class templates as
well, applying only to partial ordering, adding to the provisional
wording introduced in https://github.com/llvm/llvm-project/pull/89807.
This solves some ambuguity introduced in P0522 regarding how template
template parameters are partially ordered, and should reduce the
negative impact of enabling `-frelaxed-template-template-args` by
default.
Given the following example:
```C++
template <class T1, class T2 = float> struct A;
template <class T3> struct B;
template <template <class T4> class TT1, class T5> struct B<TT1<T5>>; // #1
template <class T6, class T7> struct B<A<T6, T7>>; // #2
template struct B<A<int>>;
```
Prior to P0522, `#2` was picked. Afterwards, this became ambiguous. This
patch restores the pre-P0522 behavior, `#2` is picked again.
Since the implementation of DR458 (d1446017), we have had an algorithm
that template parameters would take precedence over its parent scopes at
the name lookup. However, we failed to handle the following case where
the member function declaration is not yet deferral parsed (This is
where the patch of DR458 applies):
```cpp
namespace NS {
int CC;
template <typename> struct C;
}
template <typename CC>
struct NS::C {
void foo(CC);
};
```
When parsing the parameter of the function declaration `void foo(CC)`,
we used to perform a name lookup following such a Scope chain:
```
FunctionScope foo (failed)
RecordScope C (failed)
NamespaceScope NS (found `int CC`)
(If failed)
TemplateParameterScope of C
```
This doesn't seem right because according to `[temp.local]`, a template
parameter scope should be searched before its parent scope to which the
parameter appertains. This patch corrects the search scopes by setting a
lookup Entity for template parameter Scopes so that we can bail out in
CppNameLookup() when reaching the RecordScope. Afterward, the search
chain would be like:
```
FunctionScope foo (failed)
RecordScope C (failed)
TemplateParameterScope of C (found CC)
(If failed)
NamespaceScope NS
```
Fixes https://github.com/llvm/llvm-project/issues/64082
We need to rebuild the template parameters of out-of-line
definitions/specializations of member templates in the context of the
current instantiation for the purposes of declaration matching. We
already do this for function templates and class templates, but not
variable templates, partial specializations of variable template, and
partial specializations of class templates. This patch fixes the latter
cases.
fixes https://github.com/llvm/llvm-project/issues/98258
The cause is that the assertion "Nothing should reference a value below
the actual template depth" is incorrect since we can have a generic
lambda inside requires-clause of friend function template, and the
generic lambda can reference to values with greater template depth.
---------
Co-authored-by: cor3ntin <corentinjabot@gmail.com>
Because there may be multiple constrained function of the same type, we
need to perform overload resolution to find the best viable function to
specialize.
Fixes#46029
Forked from https://github.com/llvm/llvm-project/pull/102510 by
[mizvekov](https://github.com/mizvekov). Changes are captured as a fixup
commit.
There are some external projects that can't rely on our own sugar
propagation for templated entities, because they need to resugar types
which only exist within their framework, and so are entirely invisible
to our internal tooling.
This new flag is meant to prevent our transforms from removing any
Subst*
nodes.
For this, this is wired only to template type alias subsititutions.
Note that our AST does represent enough information to correctly
resugar template type alias, so any users of this are limited in their
capacity to reconstruct the parameter substitutions fully.
---------
Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
A class member named by an expression in a member function that may instantiate to a static _or_ non-static member is represented by a `UnresolvedLookupExpr` in order to defer the implicit transformation to a class member access expression until instantiation. Since `ASTContext::getDecltypeType` only creates a `DecltypeType` that has a `DependentDecltypeType` as its canonical type when the operand is instantiation dependent, and since we do not transform types unless they are instantiation dependent, we need to mark the `UnresolvedLookupExpr` as instantiation dependent in order to correctly build a `DecltypeType` using the expression as its operand with a `DependentDecltypeType` canonical type. Fixes#99873.
The selection of the most constrained candidate for member function
explicit specializations introduced in #88963 does not check whether the
selected candidate is more constrained than all other candidates, which
can result in ambiguities being undiagnosed. This patch addresses the
issue.
This makes use of the changes introduced in D134604, in order to
instantiate alias templates witn a final sugared substitution.
This comes at no additional relevant cost.
Since we don't track / unique them in specializations, we wouldn't be
able to resugar them later anyway.
Differential Revision: https://reviews.llvm.org/D136565
This is mostly a cleanups patch, with some hard to observe sugar
preservation improvements.
Except for the function template deduction changes which improve some
pre-existing diagnostics a little bit.
This reverts commit ce4aada6e2135e29839f672a6599db628b53295d and a
follow-up patch 8ef26f1289bf069ccc0d6383f2f4c0116a1206c1.
This new warning can not be fully suppressed by the
`-Wno-missing-dependent-template-keyword` flag, this gives developer no
time to do the cleanup in a large codebase, see https://github.com/llvm/llvm-project/pull/98547#issuecomment-2228250884
Split out the deduction guide related code from SemaTemplate.cpp to a
dedicated file.
These code has grown significantly, and moving it to a separate file
will improve code organization.
Reapplies #92957, fixing an instance where the `template` keyword was
missing prior to a dependent name in `llvm/ADT/ArrayRef.h`. An
_alias-declaration_ is used to work around a bug affecting GCC releases
before 11.1 (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94799) which
rejects the use of the `template` keyword prior to the
_nested-name-specifier_ in the class member access.
As described in https://github.com/llvm/llvm-project/issues/90209#issuecomment-2135972202,
Clang may not preserve enough information during template argument
deduction. This can result in a merely canonical `TemplateTypeParmType`
with a null `Decl`, leading to an incomplete template parameter list for
the synthesized deduction guide.
This patch addresses the issue by using the index and depth information
to retrieve the corresponding template parameter, rather than relying on
`TTP->getDecl()`.
Fixes#90209
This patch addresses an issue where non-template explicit deduction
guides were not considered when synthesized the deduction guides for
alias templates.
Fixes#94927.
Similar to the approach of handling nested class templates when building
a CTAD guide, we substitute the template parameters of a type alias
declaration with the instantiating template arguments in order to ensure
the guide eventually doesn't reference any outer template parameters.
For example,
```cpp
template <class T> struct Outer {
using Alias = S<T>;
template <class U> struct Inner {
Inner(Alias);
};
};
```
we used to retain the reference to T accidentally because the
TreeTransform does nothing on type alias Decls by default.
Fixes https://github.com/llvm/llvm-project/issues/94614
CWG1835 was one of the many core issues resolved by P1787R6: "Declarations and where to
find them" (http://wg21.link/p1787r6). Its resolution changes how
member-qualified names (as defined by [basic.lookup.qual.general] p2) are looked
up. This patch implementation that resolution.
Previously, an _identifier_ following `.` or `->` would be first looked
up in the type of the object expression (i.e. qualified lookup), and
then in the context of the _postfix-expression_ (i.e. unqualified
lookup) if nothing was found; the result of the second lookup was
required to name a class template. Notably, this second lookup would
occur even when the object expression was dependent, and its result
would be used to determine whether a `<` token is the start of a
_template-argument_list_.
The new wording in [basic.lookup.qual.general] p2 states:
> A member-qualified name is the (unique) component name, if any, of
> - an _unqualified-id_ or
> - a _nested-name-specifier_ of the form _`type-name ::`_ or
_`namespace-name ::`_
>
> in the id-expression of a class member access expression. A
***qualified name*** is
> - a member-qualified name or
> - the terminal name of
> - a _qualified-id_,
> - a _using-declarator_,
> - a _typename-specifier_,
> - a _qualified-namespace-specifier_, or
> - a _nested-name-specifier_, _elaborated-type-specifier_, or
_class-or-decltype_ that has a _nested-name-specifier_.
>
> The _lookup context_ of a member-qualified name is the type of its
associated object expression (considered dependent if the object
expression is type-dependent). The lookup context of any other qualified
name is the type, template, or namespace nominated by the preceding
_nested-name-specifier_.
And [basic.lookup.qual.general] p3 now states:
> _Qualified name lookup_ in a class, namespace, or enumeration performs
a search of the scope associated with it except as specified below.
Unless otherwise specified, a qualified name undergoes qualified name
lookup in its lookup context from the point where it appears unless the
lookup context either is dependent and is not the current instantiation
or is not a class or class template. If nothing is found by qualified
lookup for a member-qualified name that is the terminal name of a
_nested-name-specifier_ and is not dependent, it undergoes unqualified
lookup.
In non-standardese terms, these two paragraphs essentially state the
following:
- A name that immediately follows `.` or `->` in a class member access
expression is a member-qualified name
- A member-qualified name will be first looked up in the type of the
object expression `T` unless `T` is a dependent type that is _not_ the
current instantiation, e.g.
```
template<typename T>
struct A
{
void f(T* t)
{
this->x; // type of the object expression is 'A<T>'. although 'A<T>' is dependent, it is the
// current instantiation so we look up 'x' in the template definition context.
t->y; // type of the object expression is 'T' ('->' is transformed to '.' per [expr.ref]).
// 'T' is dependent and is *not* the current instantiation, so we lookup 'y' in the
// template instantiation context.
}
};
```
- If the first lookup finds nothing and:
- the member-qualified name is the first component of a
_nested-name-specifier_ (which could be an _identifier_ or a
_simple-template-id_), and either:
- the type of the object expression is the current instantiation and it
has no dependent base classes, or
- the type of the object expression is not dependent
then we lookup the name again, this time via unqualified lookup.
Although the second (unqualified) lookup is stated not to occur when the
member-qualified name is dependent, a dependent name will _not_ be
dependent once the template is instantiated, so the second lookup must
"occur" during instantiation if qualified lookup does not find anything.
This means that we must perform the second (unqualified) lookup during
parsing even when the type of the object expression is dependent, but
those results are _not_ used to determine whether a `<` token is the
start of a _template-argument_list_; they are stored so we can replicate
the second lookup during instantiation.
In even simpler terms (paraphrasing the meeting minutes from the review of P1787; see https://wiki.edg.com/bin/view/Wg21summer2020/P1787%28Lookup%29Review2020-06-15Through2020-06-18):
- Unqualified lookup always happens for the first name in a
_nested-name-specifier_ that follows `.` or `->`
- The result of that lookup is only used to determine whether `<` is the
start of a _template-argument-list_ if the first (qualified) lookup
found nothing and the lookup context:
- is not dependent, or
- is the current instantiation and has no dependent base classes.
An example:
```
struct A
{
void f();
};
template<typename T>
using B = A;
template<typename T>
struct C : A
{
template<typename U>
void g();
void h(T* t)
{
this->g<int>(); // ok, '<' is the start of a template-argument-list ('g' was found via qualified lookup in the current instantiation)
this->B<void>::f(); // ok, '<' is the start of a template-argument-list (current instantiation has no dependent bases, 'B' was found via unqualified lookup)
t->g<int>(); // error: '<' means less than (unqualified lookup does not occur for a member-qualified name that isn't the first component of a nested-name-specifier)
t->B<void>::f(); // error: '<' means less than (unqualified lookup does not occur if the name is dependent)
t->template B<void>::f(); // ok: '<' is the start of a template-argument-list ('template' keyword used)
}
};
```
Some additional notes:
- Per [basic.lookup.qual.general] p1, lookup for a
member-qualified name only considers namespaces, types, and templates
whose specializations are types if it's an _identifier_ followed by
`::`; lookup for the component name of a _simple-template-id_ followed
by `::` is _not_ subject to this rule.
- The wording which specifies when the second unqualified lookup occurs
appears to be paradoxical. We are supposed to do it only for the first
component name of a _nested-name-specifier_ that follows `.` or `->`
when qualified lookup finds nothing. However, when that name is followed
by `<` (potentially starting a _simple-template-id_) we don't _know_
whether it will be the start of a _nested-name-specifier_ until we do
the lookup -- but we aren't supposed to do the lookup until we know it's
part of a _nested-name-specifier_! ***However***, since we only do the
second lookup when the first lookup finds nothing (and the name isn't
dependent), ***and*** since neither lookup is type-only, the only valid
option is for the name to be the _template-name_ in a
_simple-template-id_ that is followed by `::` (it can't be an
_unqualified-id_ naming a member because we already determined that the
lookup context doesn't have a member with that name). Thus, we can lock
into the _nested-name-specifier_ interpretation and do the second lookup
without having to know whether the _simple-template-id_ will be followed
by `::` yet.
In the https://github.com/llvm/llvm-project/pull/90961 fix, we miss a
case where the undeduced template parameters of the underlying deduction
guide are not transformed, which leaves incorrect depth/index
information, and causes crashes when evaluating constraints.
This patch fix this missing case.
Fixes#92596Fixes#92212