frederic-tingaud-sonarsource created this revision.
frederic-tingaud-sonarsource added a reviewer: rnk.
Herald added a project: All.
frederic-tingaud-sonarsource requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
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:
cpp
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.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D130709
Files:
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaTemplate/ms-unqualified-base-class.cpp
Index: clang/test/SemaTemplate/ms-unqualified-base-class.cpp
===================================================================
--- clang/test/SemaTemplate/ms-unqualified-base-class.cpp
+++ clang/test/SemaTemplate/ms-unqualified-base-class.cpp
@@ -83,3 +83,37 @@
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@+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@+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>;
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -4308,11 +4308,21 @@
}
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()) {
+ QualType BT = cast<ElaboratedType>(Base.getType())->getNamedType();
+ const auto *BaseTemplate =
dyn_cast<TemplateSpecializationType>(BT);
+ if (BaseTemplate && Context.hasSameTemplateName(
+ BaseTemplate->getTemplateName(), TN)) {
+ Diag(IdLoc, diag::ext_unqualified_base_class)
+ << SourceRange(IdLoc, Init->getSourceRange().getEnd());
+ BaseType = BT;
+ break;
+ }
+ }
}
}
Index: clang/test/SemaTemplate/ms-unqualified-base-class.cpp
===================================================================
--- clang/test/SemaTemplate/ms-unqualified-base-class.cpp
+++ clang/test/SemaTemplate/ms-unqualified-base-class.cpp
@@ -83,3 +83,37 @@
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@+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@+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>;
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -4308,11 +4308,21 @@
}
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()) {
+ QualType BT = cast<ElaboratedType>(Base.getType())->getNamedType();
+ const auto *BaseTemplate = dyn_cast<TemplateSpecializationType>(BT);
+ if (BaseTemplate && Context.hasSameTemplateName(
+ BaseTemplate->getTemplateName(), TN)) {
+ Diag(IdLoc, diag::ext_unqualified_base_class)
+ << SourceRange(IdLoc, Init->getSourceRange().getEnd());
+ BaseType = BT;
+ break;
+ }
+ }
}
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits