[clang] ba1c396 - MSVC compatibility mode: fix error on unqualified templated base class initialization in case of partial specialization

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 16 08:10:21 PDT 2022


Author: Fred Tingaud
Date: 2022-08-16T17:09:55+02:00
New Revision: ba1c396e09a6dc56d817df0d378f3c826bbacaaa

URL: https://github.com/llvm/llvm-project/commit/ba1c396e09a6dc56d817df0d378f3c826bbacaaa
DIFF: https://github.com/llvm/llvm-project/commit/ba1c396e09a6dc56d817df0d378f3c826bbacaaa.diff

LOG: MSVC compatibility mode: fix error on unqualified templated base class initialization in case of partial specialization

I introduced a patch to handle unqualified templated base class
initialization in MSVC compatibility mode:
https://reviews.llvm.org/rGc894e85fc64dd8d83b460de81080fff93c5ca334
We identified a problem with this patch in the case where the base class
is partially specialized, which can lead to triggering an assertion in
the case of a mix between types and values.
The minimal test case is:

  template <typename Type, int TSize> class Vec {};
  template <int TDim> class Index : public Vec<int, TDim> {
    Index() : Vec() {}
  };
  template class Index<0>;

The detailed problem is that I was using the
`InjectedClassNameSpecialization`, to which the class template arguments
were then applied in order. But in the process, we were losing all the
partial specializations of the base class and creating an index mismatch
between the expected and passed arguments.

Patch By: frederic-tingaud-sonarsource

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D130709

Added: 
    

Modified: 
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/test/SemaTemplate/ms-unqualified-base-class.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 78c39197e47bb..9ab009488c955 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4309,11 +4309,21 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
       }
 
       if (getLangOpts().MSVCCompat && !getLangOpts().CPlusPlus20) {
-        auto UnqualifiedBase = R.getAsSingle<ClassTemplateDecl>();
-        if (UnqualifiedBase) {
-          Diag(IdLoc, diag::ext_unqualified_base_class)
-              << SourceRange(IdLoc, Init->getSourceRange().getEnd());
-          BaseType = UnqualifiedBase->getInjectedClassNameSpecialization();
+        if (auto UnqualifiedBase = R.getAsSingle<ClassTemplateDecl>()) {
+          auto *TempSpec = cast<TemplateSpecializationType>(
+              UnqualifiedBase->getInjectedClassNameSpecialization());
+          TemplateName TN = TempSpec->getTemplateName();
+          for (auto const &Base : ClassDecl->bases()) {
+            auto BaseTemplate =
+                Base.getType()->getAs<TemplateSpecializationType>();
+            if (BaseTemplate && Context.hasSameTemplateName(
+                                    BaseTemplate->getTemplateName(), TN)) {
+              Diag(IdLoc, diag::ext_unqualified_base_class)
+                  << SourceRange(IdLoc, Init->getSourceRange().getEnd());
+              BaseType = Base.getType();
+              break;
+            }
+          }
         }
       }
 

diff  --git a/clang/test/SemaTemplate/ms-unqualified-base-class.cpp b/clang/test/SemaTemplate/ms-unqualified-base-class.cpp
index 6d9a072769c63..5e926c5087f93 100644
--- a/clang/test/SemaTemplate/ms-unqualified-base-class.cpp
+++ b/clang/test/SemaTemplate/ms-unqualified-base-class.cpp
@@ -83,3 +83,37 @@ int main() {
 
   return I;
 }
+
+template <typename Type, int TSize> class Vec {}; // expected-note {{template is declared here}}
+
+template <int TDim> class Index : public Vec<int, TDim> {
+  // after-error at +1 {{member initializer 'Vec' does not name a non-static data member or base class}}
+  Index() : Vec() {} // before-warning {{unqualified base initializer of class templates is a Microsoft extension}}
+};
+
+template class Index<0>;
+
+template <typename T> class Array : public Vec<T, 4> {
+  // after-error at +1 {{member initializer 'Vec' does not name a non-static data member or base class}}
+  Array() : Vec() {} // before-warning {{unqualified base initializer of class templates is a Microsoft extension}}
+};
+
+template class Array<double>;
+
+template <typename T> class Wrong : public Vec<T, 4> {
+  Wrong() : NonExistent() {} // expected-error {{member initializer 'NonExistent' does not name a non-static data member or base class}}
+};
+
+template class Wrong<double>;
+
+template <typename T> class Wrong2 : public Vec<T, 4> {
+  Wrong2() : Vec<T>() {} // expected-error {{too few template arguments for class template 'Vec'}}
+};
+
+template class Wrong2<double>;
+
+template <typename T> class Wrong3 : public Vec<T, 4> {
+  Wrong3() : Base() {} // expected-error {{member initializer 'Base' does not name a non-static data member or base class}}
+};
+
+template class Wrong3<double>;


        


More information about the cfe-commits mailing list