Skip to content

Commit ae04671

Browse files
bolshakov-atstellar
authored andcommitted
[clang] Represent array refs as TemplateArgument::Declaration (#80050)
This returns (probably temporarily) array-referring NTTP behavior to which was prior to #78041 because ~~I'm fed up~~ have no time to fix regressions. (cherry picked from commit 9bf4e54)
1 parent 140ad18 commit ae04671

File tree

2 files changed

+37
-20
lines changed

2 files changed

+37
-20
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7412,9 +7412,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
74127412
if (ArgResult.isInvalid())
74137413
return ExprError();
74147414

7415-
// Prior to C++20, enforce restrictions on possible template argument
7416-
// values.
7417-
if (!getLangOpts().CPlusPlus20 && Value.isLValue()) {
7415+
if (Value.isLValue()) {
7416+
APValue::LValueBase Base = Value.getLValueBase();
7417+
auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>());
74187418
// For a non-type template-parameter of pointer or reference type,
74197419
// the value of the constant expression shall not refer to
74207420
assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
@@ -7423,33 +7423,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
74237423
// -- a string literal
74247424
// -- the result of a typeid expression, or
74257425
// -- a predefined __func__ variable
7426-
APValue::LValueBase Base = Value.getLValueBase();
7427-
auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>());
74287426
if (Base &&
74297427
(!VD ||
74307428
isa<LifetimeExtendedTemporaryDecl, UnnamedGlobalConstantDecl>(VD))) {
74317429
Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
74327430
<< Arg->getSourceRange();
74337431
return ExprError();
74347432
}
7435-
// -- a subobject [until C++20]
7436-
if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
7437-
VD && VD->getType()->isArrayType() &&
7433+
7434+
if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 && VD &&
7435+
VD->getType()->isArrayType() &&
74387436
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
74397437
!Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
7440-
// Per defect report (no number yet):
7441-
// ... other than a pointer to the first element of a complete array
7442-
// object.
7443-
} else if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
7444-
Value.isLValueOnePastTheEnd()) {
7445-
Diag(StartLoc, diag::err_non_type_template_arg_subobject)
7446-
<< Value.getAsString(Context, ParamType);
7447-
return ExprError();
7438+
SugaredConverted = TemplateArgument(VD, ParamType);
7439+
CanonicalConverted = TemplateArgument(
7440+
cast<ValueDecl>(VD->getCanonicalDecl()), CanonParamType);
7441+
return ArgResult.get();
7442+
}
7443+
7444+
// -- a subobject [until C++20]
7445+
if (!getLangOpts().CPlusPlus20) {
7446+
if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
7447+
Value.isLValueOnePastTheEnd()) {
7448+
Diag(StartLoc, diag::err_non_type_template_arg_subobject)
7449+
<< Value.getAsString(Context, ParamType);
7450+
return ExprError();
7451+
}
7452+
assert((VD || !ParamType->isReferenceType()) &&
7453+
"null reference should not be a constant expression");
7454+
assert((!VD || !ParamType->isNullPtrType()) &&
7455+
"non-null value of type nullptr_t?");
74487456
}
7449-
assert((VD || !ParamType->isReferenceType()) &&
7450-
"null reference should not be a constant expression");
7451-
assert((!VD || !ParamType->isNullPtrType()) &&
7452-
"non-null value of type nullptr_t?");
74537457
}
74547458

74557459
if (Value.isAddrLabelDiff())

clang/test/CoverageMapping/templates.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,16 @@ int main() {
1919
func<bool>(true);
2020
return 0;
2121
}
22+
23+
namespace structural_value_crash {
24+
template <int* p>
25+
void tpl_fn() {
26+
(void)p;
27+
}
28+
29+
int arr[] = {1, 2, 3};
30+
31+
void test() {
32+
tpl_fn<arr>();
33+
}
34+
}

0 commit comments

Comments
 (0)