Skip to content

Commit 082356c

Browse files
committed
Fix the over aggressive check on parameter pack from template
Fix some UT Signed-off-by: acassagnes <acassagnes@bloomberg.net>
1 parent fad02ea commit 082356c

4 files changed

Lines changed: 46 additions & 4 deletions

File tree

clang/lib/AST/ExprConstantMeta.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,8 +1112,8 @@ static bool getParameterName(ParmVarDecl *PVD, std::string &Out) {
11121112
// instantiation's, and pack-substituted parameters were already
11131113
// filtered above.)
11141114
if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
1115-
Pattern && llvm::none_of(Pattern->parameters(), [](const ParmVarDecl *P) {
1116-
return P->isParameterPack();
1115+
Pattern && llvm::none_of(Pattern->parameters(), [&](const ParmVarDecl *P) {
1116+
return P->isParameterPack() && P->getFunctionScopeIndex() <= ParamIdx;
11171117
}))
11181118
FD = Pattern;
11191119

libcxx/include/meta

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,7 +2384,13 @@ consteval auto data_member_spec(info member_type,
23842384
bool has_name = options.name.has_value();
23852385
int alignment = options.alignment.value_or(0);
23862386
int width = options.width.value_or(0);
2387+
// 'no_unique_address' is intentionally deprecated in favor of
2388+
// '.attributes = { ^^[[no_unique_address]] }', but is still honored here for
2389+
// backward compatibility; suppress the deprecation warning at this read site.
2390+
#pragma clang diagnostic push
2391+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
23872392
bool no_unique_address = options.no_unique_address;
2393+
#pragma clang diagnostic pop
23882394
23892395
if (width) {
23902396
if (alignment)

libcxx/test/std/experimental/reflection/p3385-function-attributes.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// UNSUPPORTED: c++03 || c++11 || c++14 || c++17 || c++20
1212
// ADDITIONAL_COMPILE_FLAGS: -freflection
13-
// ADDITIONAL_COMPILE_FLAGS: -freflection-new-syntax
13+
// ADDITIONAL_COMPILE_FLAGS: -freflection-latest
1414
// ADDITIONAL_COMPILE_FLAGS: -fattribute-reflection
1515

1616
// <experimental/reflection>

libcxx/test/std/experimental/reflection/param-name-consistency-instantiation.pass.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8-
// ADDITIONAL_COMPILE_FLAGS: -freflection-latest -fparameter-reflection
8+
// ADDITIONAL_COMPILE_FLAGS: -freflection-latest -fparameter-reflection -Wno-unused-parameter -Wno-deprecated-declarations
99

1010
// <experimental/meta>
1111

@@ -47,4 +47,40 @@ static_assert(!has_identifier(param0("f")));
4747
static_assert(has_identifier(param0("g")));
4848
static_assert(identifier_of(param0("g")) == "width");
4949

50+
template <class T> struct P {
51+
template <class... Args> void h(int value, Args... rest);
52+
};
53+
template <class T> template <class... Args>
54+
void P<T>::h(int val, Args... rest) {}
55+
56+
template void P<int>::h<float>(int, float);
57+
58+
// The non-pack parameter "value"/"val" is inconsistently named. The pack sits at
59+
// pattern index 1, i.e. AFTER the queried index 0, so the query still walks the
60+
// pattern's declaration chain and detects the inconsistency.
61+
static_assert(!has_identifier(parameters_of(^^P<int>::h<float>)[0]));
62+
63+
// A named parameter positioned AFTER a function parameter pack. Instantiating
64+
// with TWO pack elements makes "tail" land at instantiation index 3, while it
65+
// sits at index 2 in the pattern (where the pack is a single parameter). Because
66+
// a pack precedes the queried index, the query cannot safely index the pattern's
67+
// shorter parameter list and falls back to the instantiation. This must neither
68+
// misindex nor crash -- getParamDecl(3) on the 3-parameter pattern would be
69+
// out-of-bounds.
70+
template <class T> struct Q {
71+
template <class... Args> void k(int value, Args... rest, int tail);
72+
};
73+
template <class T> template <class... Args>
74+
void Q<T>::k(int val, Args... rest, int tail) {}
75+
76+
template void Q<int>::k<float, double>(int, float, double, int);
77+
78+
// Pre-pack parameter (index 0): inconsistent name, detected via the pattern.
79+
static_assert(!has_identifier(parameters_of(^^Q<int>::k<float, double>)[0]));
80+
81+
// Trailing parameter after the pack (instantiation index 3, pattern index 2):
82+
// must not crash; reports its consistently-spelled name.
83+
static_assert(has_identifier(parameters_of(^^Q<int>::k<float, double>)[3]));
84+
static_assert(identifier_of(parameters_of(^^Q<int>::k<float, double>)[3]) == "tail");
85+
5086
int main(int, char**) { return 0; }

0 commit comments

Comments
 (0)