llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

<details>
<summary>Changes</summary>

A template parameter object is an lvalue, which was not being respected for 
injected parameters.

Fixes GH101394

---
Full diff: https://github.com/llvm/llvm-project/pull/101395.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+3-1) 
- (modified) clang/lib/AST/ASTContext.cpp (+12-4) 
- (modified) clang/lib/AST/ExprClassification.cpp (+5-4) 
- (modified) clang/test/SemaTemplate/temp_arg_template_p0522.cpp (+18) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c2e0282d1c72..bb8f45887e01e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -130,7 +130,7 @@ Improvements to Clang's diagnostics
 - Some template related diagnostics have been improved.
 
   .. code-block:: c++
-    
+
      void foo() { template <typename> int i; } // error: templates can only be 
declared in namespace or class scope
 
      struct S {
@@ -170,6 +170,8 @@ Bug Fixes to C++ Support
 - Fixed a failed assertion when checking invalid delete operator declaration. 
(#GH96191)
 - Fix a crash when checking destructor reference with an invalid initializer. 
(#GH97230)
 - Clang now correctly parses potentially declarative nested-name-specifiers in 
pointer-to-member declarators.
+- Fix a crash when matching template template parameters with templates which 
have
+  parameters of different class type. (#GH101394)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a465cdfcf3c89..5a90087882c85 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5588,11 +5588,19 @@ TemplateArgument 
ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
     // of a real template argument.
     // FIXME: It would be more faithful to model this as something like an
     // lvalue-to-rvalue conversion applied to a const-qualified lvalue.
-    if (T->isRecordType())
+    ExprValueKind VK;
+    if (T->isRecordType()) {
+      // C++ [temp.param]p8: An id-expression naming a non-type
+      // template-parameter of class type T denotes a static storage duration
+      // object of type const T.
       T.addConst();
-    Expr *E = new (*this) DeclRefExpr(
-        *this, NTTP, /*RefersToEnclosingVariableOrCapture*/ false, T,
-        Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
+      VK = VK_LValue;
+    } else {
+      VK = Expr::getValueKindForType(NTTP->getType());
+    }
+    Expr *E = new (*this)
+        DeclRefExpr(*this, NTTP, /*RefersToEnclosingVariableOrCapture=*/false,
+                    T, VK, NTTP->getLocation());
 
     if (NTTP->isParameterPack())
       E = new (*this)
diff --git a/clang/lib/AST/ExprClassification.cpp 
b/clang/lib/AST/ExprClassification.cpp
index 6482cb6d39acc..d80e3a19a469b 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -471,12 +471,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const 
Expr *E) {
 /// ClassifyDecl - Return the classification of an expression referencing the
 /// given declaration.
 static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
-  // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
-  //   function, variable, or data member and a prvalue otherwise.
+  // C++ [expr.prim.id.unqual]p3: The result is an lvalue if the entity is a
+  // function, variable, or data member, or a template parameter object and a
+  // prvalue otherwise.
   // In C, functions are not lvalues.
   // In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
-  // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
-  // special-case this.
+  // lvalue unless it's a reference type or a class type (C++ [temp.param]p8),
+  // so we need to special-case this.
 
   if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
     if (M->isImplicitObjectMemberFunction())
diff --git a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp 
b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
index 251b6fc7d2be1..6f6568b9ab776 100644
--- a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
@@ -126,3 +126,21 @@ namespace GH62529 {
   template<class T4> B<A, T4> f();
   auto t = f<int>();
 } // namespace GH62529
+
+namespace GH101394 {
+  struct X {};
+  struct Y {
+    constexpr Y(const X &) {}
+  };
+
+  namespace t1 {
+    template<template<X> class> struct A {};
+    template<Y> struct B;
+    template struct A<B>;
+  } // namespace t1
+  namespace t2 {
+    template<template<Y> class> struct A {};
+    template<X> struct B;
+    template struct A<B>; // expected-error {{different template parameters}}
+  } // namespace t2
+} // namespace GH101394

``````````

</details>


https://github.com/llvm/llvm-project/pull/101395
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to