Skip to content

Commit

Permalink
[clang][Sema] Avoid guessing unexpanded packs' size in getFullyPackEx…
Browse files Browse the repository at this point in the history
…pandedSize (#87768)

There has been an optimization for `SizeOfPackExprs` since c5452ed, in
which
we overlooked a case where the template arguments were not yet
formed into a `PackExpansionType` at the token annotation stage. This
led to a problem in that a template involving such expressions may
lose its nature of being dependent, causing some false-positive
diagnostics.

Fixes #84220
  • Loading branch information
zyn0217 committed Apr 10, 2024
1 parent 89ba7e1 commit a0651db
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ Bug Fixes to C++ Support
- Fix crash when inheriting from a cv-qualified type. Fixes:
(`#35603 <https://github.com/llvm/llvm-project/issues/35603>`_)
- Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790).
- Handled an edge case in ``getFullyPackExpandedSize`` so that we now avoid a false-positive diagnostic. (#GH84220)
- Clang now correctly tracks type dependence of by-value captures in lambdas with an explicit
object parameter.
Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399).
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,17 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
// expanded this pack expansion into the enclosing pack if we could.
if (Elem.isPackExpansion())
return std::nullopt;
// Don't guess the size of unexpanded packs. The pack within a template
// argument may have yet to be of a PackExpansion type before we see the
// ellipsis in the annotation stage.
//
// This doesn't mean we would invalidate the optimization: Arg can be an
// unexpanded pack regardless of Elem's dependence. For instance,
// A TemplateArgument that contains either a SubstTemplateTypeParmPackType
// or SubstNonTypeTemplateParmPackExpr is always considered Unexpanded, but
// the underlying TemplateArgument thereof may not.
if (Elem.containsUnexpandedParameterPack())
return std::nullopt;
}
return Pack.pack_size();
}
Expand Down
23 changes: 23 additions & 0 deletions clang/test/SemaTemplate/alias-templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,29 @@ namespace PR14858 {
void test_q(int (&a)[5]) { Q<B, B, B>().f<B, B>(&a); }
}

namespace PR84220 {

template <class...> class list {};

template <int> struct foo_impl {
template <class> using f = int;
};

template <class... xs>
using foo = typename foo_impl<sizeof...(xs)>::template f<xs...>;

// We call getFullyPackExpandedSize at the annotation stage
// before parsing the ellipsis next to the foo<xs>. This happens before
// a PackExpansionType is formed for foo<xs>.
// getFullyPackExpandedSize shouldn't determine the value here. Otherwise,
// foo_impl<sizeof...(xs)> would lose its dependency despite the template
// arguments being unsubstituted.
template <class... xs> using test = list<foo<xs>...>;

test<int> a;

}

namespace redecl {
template<typename> using A = int;
template<typename = void> using A = int;
Expand Down

0 comments on commit a0651db

Please sign in to comment.