Skip to content

Commit 1299af6

Browse files
authored
[clang] create class-type injected NTTP with correct value kind (#101395)
A template parameter object is an lvalue, which was not being respected for injected parameters. Fixes #101394
1 parent cad8352 commit 1299af6

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ Bug Fixes to C++ Support
173173
- Clang now correctly parses potentially declarative nested-name-specifiers in pointer-to-member declarators.
174174
- Fix a crash when checking the initialzier of an object that was initialized
175175
with a string literal. (#GH82167)
176+
- Fix a crash when matching template template parameters with templates which have
177+
parameters of different class type. (#GH101394)
176178

177179
Bug Fixes to AST Handling
178180
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/ASTContext.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5588,11 +5588,19 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
55885588
// of a real template argument.
55895589
// FIXME: It would be more faithful to model this as something like an
55905590
// lvalue-to-rvalue conversion applied to a const-qualified lvalue.
5591-
if (T->isRecordType())
5591+
ExprValueKind VK;
5592+
if (T->isRecordType()) {
5593+
// C++ [temp.param]p8: An id-expression naming a non-type
5594+
// template-parameter of class type T denotes a static storage duration
5595+
// object of type const T.
55925596
T.addConst();
5593-
Expr *E = new (*this) DeclRefExpr(
5594-
*this, NTTP, /*RefersToEnclosingVariableOrCapture*/ false, T,
5595-
Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
5597+
VK = VK_LValue;
5598+
} else {
5599+
VK = Expr::getValueKindForType(NTTP->getType());
5600+
}
5601+
Expr *E = new (*this)
5602+
DeclRefExpr(*this, NTTP, /*RefersToEnclosingVariableOrCapture=*/false,
5603+
T, VK, NTTP->getLocation());
55965604

55975605
if (NTTP->isParameterPack())
55985606
E = new (*this)

clang/lib/AST/ExprClassification.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
485485
/// ClassifyDecl - Return the classification of an expression referencing the
486486
/// given declaration.
487487
static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
488-
// C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
489-
// function, variable, or data member and a prvalue otherwise.
488+
// C++ [expr.prim.id.unqual]p3: The result is an lvalue if the entity is a
489+
// function, variable, or data member, or a template parameter object and a
490+
// prvalue otherwise.
490491
// In C, functions are not lvalues.
491492
// In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
492-
// lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
493-
// special-case this.
493+
// lvalue unless it's a reference type or a class type (C++ [temp.param]p8),
494+
// so we need to special-case this.
494495

495496
if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
496497
if (M->isImplicitObjectMemberFunction())

clang/test/SemaTemplate/temp_arg_template_p0522.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,21 @@ namespace GH62529 {
126126
template<class T4> B<A, T4> f();
127127
auto t = f<int>();
128128
} // namespace GH62529
129+
130+
namespace GH101394 {
131+
struct X {};
132+
struct Y {
133+
constexpr Y(const X &) {}
134+
};
135+
136+
namespace t1 {
137+
template<template<X> class> struct A {};
138+
template<Y> struct B;
139+
template struct A<B>;
140+
} // namespace t1
141+
namespace t2 {
142+
template<template<Y> class> struct A {};
143+
template<X> struct B;
144+
template struct A<B>; // expected-error {{different template parameters}}
145+
} // namespace t2
146+
} // namespace GH101394

0 commit comments

Comments
 (0)