Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[clang] Implement CWG2398 provisional TTP matching to class templates" #93258

Conversation

mizvekov
Copy link
Contributor

Reverts #92855

This is causing issues, there are still being reduced, but does look like a problem.

@mizvekov mizvekov self-assigned this May 24, 2024
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 24, 2024
@llvmbot
Copy link
Member

llvmbot commented May 24, 2024

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

Changes

Reverts llvm/llvm-project#92855

This is causing issues, there are still being reduced, but does look like a problem.


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

4 Files Affected:

  • (modified) clang/lib/Sema/SemaTemplate.cpp (+1-4)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+30-46)
  • (modified) clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp (+2-3)
  • (modified) clang/test/SemaTemplate/cwg2398.cpp (+3)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 268f079980a6c..39e9dbed0c3e0 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1807,8 +1807,6 @@ static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
 // Returns the template parameter list with all default template argument
 // information.
 static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
-  if (TD->isImplicit())
-    return TD->getTemplateParameters();
   // Make sure we get the template parameter list from the most
   // recent declaration, since that is the only one that is guaranteed to
   // have all the default template argument information.
@@ -1829,8 +1827,7 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
   //    template <class = void> friend struct C;
   //  };
   //  template struct S<int>;
-  while ((D->isImplicit() ||
-          D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) &&
+  while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None &&
          D->getPreviousDecl())
     D = D->getPreviousDecl();
   return cast<TemplateDecl>(D)->getTemplateParameters();
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 08a69d3cb2589..f9ec34163e656 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -527,8 +527,8 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A,
     R->setDefaultArgument(
         S.Context,
         S.getTrivialTemplateArgumentLoc(Default, QualType(), SourceLocation()));
-    if (T->hasTypeConstraint()) {
-      auto *C = T->getTypeConstraint();
+    if (R->hasTypeConstraint()) {
+      auto *C = R->getTypeConstraint();
       R->setTypeConstraint(C->getConceptReference(),
                            C->getImmediatelyDeclaredConstraint());
     }
@@ -583,53 +583,37 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
       return TemplateDeductionResult::Success;
 
     auto NewDeduced = DeducedTemplateArgument(Arg);
-    // Provisional resolution for CWG2398: If Arg names a template
-    // specialization, then we deduce a synthesized template template parameter
-    // based on A, but using the TS's arguments as defaults.
-    if (DefaultArguments.size() != 0) {
+    // Provisional resolution for CWG2398: If Arg is also a template template
+    // param, and it names a template specialization, then we deduce a
+    // synthesized template template parameter based on A, but using the TS's
+    // arguments as defaults.
+    if (auto *TempArg = dyn_cast_or_null<TemplateTemplateParmDecl>(
+            Arg.getAsTemplateDecl())) {
       assert(Arg.getKind() == TemplateName::Template);
-      TemplateDecl *TempArg = Arg.getAsTemplateDecl();
+      assert(!TempArg->isExpandedParameterPack());
+
       TemplateParameterList *As = TempArg->getTemplateParameters();
-      assert(DefaultArguments.size() <= As->size());
-
-      SmallVector<NamedDecl *, 4> Params(As->size());
-      for (unsigned I = 0; I < DefaultArguments.size(); ++I)
-        Params[I] = getTemplateParameterWithDefault(S, As->getParam(I),
-                                                    DefaultArguments[I]);
-      for (unsigned I = DefaultArguments.size(); I < As->size(); ++I)
-        Params[I] = As->getParam(I);
-      // FIXME: We could unique these, and also the parameters, but we don't
-      // expect programs to contain a large enough amount of these deductions
-      // for that to be worthwhile.
-      auto *TPL = TemplateParameterList::Create(
-          S.Context, SourceLocation(), SourceLocation(), Params,
-          SourceLocation(), As->getRequiresClause());
-
-      TemplateDecl *TD;
-      switch (TempArg->getKind()) {
-      case Decl::TemplateTemplateParm: {
-        auto *A = cast<TemplateTemplateParmDecl>(TempArg);
-        assert(!A->isExpandedParameterPack());
-        TD = TemplateTemplateParmDecl::Create(
-            S.Context, A->getDeclContext(), SourceLocation(), A->getDepth(),
-            A->getPosition(), A->isParameterPack(), A->getIdentifier(),
-            A->wasDeclaredWithTypename(), TPL);
-        break;
-      }
-      case Decl::ClassTemplate: {
-        auto *A = cast<ClassTemplateDecl>(TempArg);
-        auto *CT = ClassTemplateDecl::Create(S.Context, A->getDeclContext(),
-                                             SourceLocation(), A->getDeclName(),
-                                             TPL, A->getTemplatedDecl());
-        CT->setPreviousDecl(A);
-        TD = CT;
-        break;
-      }
-      default:
-        llvm_unreachable("Unexpected Template Kind");
+      if (DefaultArguments.size() != 0) {
+        assert(DefaultArguments.size() <= As->size());
+        SmallVector<NamedDecl *, 4> Params(As->size());
+        for (unsigned I = 0; I < DefaultArguments.size(); ++I)
+          Params[I] = getTemplateParameterWithDefault(S, As->getParam(I),
+                                                      DefaultArguments[I]);
+        for (unsigned I = DefaultArguments.size(); I < As->size(); ++I)
+          Params[I] = As->getParam(I);
+        // FIXME: We could unique these, and also the parameters, but we don't
+        // expect programs to contain a large enough amount of these deductions
+        // for that to be worthwhile.
+        auto *TPL = TemplateParameterList::Create(
+            S.Context, SourceLocation(), SourceLocation(), Params,
+            SourceLocation(), As->getRequiresClause());
+        NewDeduced = DeducedTemplateArgument(
+            TemplateName(TemplateTemplateParmDecl::Create(
+                S.Context, TempArg->getDeclContext(), SourceLocation(),
+                TempArg->getDepth(), TempArg->getPosition(),
+                TempArg->isParameterPack(), TempArg->getIdentifier(),
+                TempArg->wasDeclaredWithTypename(), TPL)));
       }
-      TD->setImplicit(true);
-      NewDeduced = DeducedTemplateArgument(TemplateName(TD));
     }
 
     DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp
index bc39431253880..a5b39fe5c51f7 100644
--- a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp
@@ -28,14 +28,13 @@ namespace StdExample {
     { /* ... */ }
 
   template<template<class> class TT>
-    void f(TT<int>);
+    void f(TT<int>); // expected-note {{candidate template ignored}}
 
   template<template<class,class> class TT>
     void g(TT<int, Alloc<int>>);
 
   int h() {
-    f(v); // OK: TT = vector, Alloc<int> is used as the default argument for the
-          // second parameter.
+    f(v); // expected-error {{no matching function for call to 'f'}}
     g(v); // OK: TT = vector
   }
 
diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp
index 4cc946735a1e2..e3b5e575374d3 100644
--- a/clang/test/SemaTemplate/cwg2398.cpp
+++ b/clang/test/SemaTemplate/cwg2398.cpp
@@ -65,10 +65,13 @@ namespace class_template {
   template <class T3> struct B;
 
   template <template <class T4> class TT1, class T5> struct B<TT1<T5>>;
+  // new-note@-1 {{partial specialization matches}}
 
   template <class T6, class T7> struct B<A<T6, T7>> {};
+  // new-note@-1 {{partial specialization matches}}
 
   template struct B<A<int>>;
+  // new-error@-1 {{ambiguous partial specialization}}
 } // namespace class_template
 
 namespace type_pack1 {

@mizvekov mizvekov merged commit 06aadbe into main May 24, 2024
6 of 8 checks passed
@mizvekov mizvekov deleted the revert-92855-users/mizvekov/clang-cwg2398-ttp-matches-class-template branch May 24, 2024 00:33
@dcci
Copy link
Member

dcci commented May 24, 2024

Thanks. I'll try to get a repro (it's reducing from a large codebase so it might take some time)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants