Author: Fred Tingaud Date: 2022-05-05T16:03:39+02:00 New Revision: c894e85fc64dd8d83b460de81080fff93c5ca334
URL: https://github.com/llvm/llvm-project/commit/c894e85fc64dd8d83b460de81080fff93c5ca334 DIFF: https://github.com/llvm/llvm-project/commit/c894e85fc64dd8d83b460de81080fff93c5ca334.diff LOG: In MSVC compatibility mode, handle unqualified templated base class initialization Before C++20, MSVC was supporting not mentioning the template argument of the base class when initializing a class inheriting a templated base class. So the following code compiled correctly: ``` template <class T> class Base { }; template <class T> class Derived : public Base<T> { public: Derived() : Base() {} }; void test() { Derived<int> d; } ``` See https://godbolt.org/z/Pxxe7nccx for a conformance view. This patch adds support for such construct when in MSVC compatibility mode. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D124666 Added: clang/test/SemaTemplate/ms-unqualified-base-class.cpp Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDeclCXX.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 45540fae58538..614bacc34af51 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5509,6 +5509,9 @@ def err_found_later_in_class : Error<"member %0 used before its declaration">; def ext_found_later_in_class : ExtWarn< "use of member %0 before its declaration is a Microsoft extension">, InGroup<MicrosoftTemplate>; +def ext_unqualified_base_class : ExtWarn< + "unqualified base initializer of class templates is a Microsoft extension">, + InGroup<MicrosoftTemplate>; def note_dependent_member_use : Note< "must qualify identifier to find this declaration in dependent base class">; def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither " diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b45e8e396b31a..a16fe0b1b72a4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4307,6 +4307,15 @@ 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 no results were found, try to correct typos. TypoCorrection Corr; MemInitializerValidatorCCC CCC(ClassDecl); diff --git a/clang/test/SemaTemplate/ms-unqualified-base-class.cpp b/clang/test/SemaTemplate/ms-unqualified-base-class.cpp new file mode 100644 index 0000000000000..6d9a072769c63 --- /dev/null +++ b/clang/test/SemaTemplate/ms-unqualified-base-class.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -std=c++17 -fms-compatibility -fsyntax-only -verify=before,expected %s +// RUN: %clang_cc1 -std=c++17 -fms-compatibility -fdelayed-template-parsing -fsyntax-only -verify=before,expected %s +// RUN: %clang_cc1 -std=c++20 -fms-compatibility -fsyntax-only -verify=after,expected %s +// RUN: %clang_cc1 -std=c++20 -fms-compatibility -fdelayed-template-parsing -fsyntax-only -verify=after,expected %s + +template <class T> +class Base { +}; + +template <class T> +class Based {}; // Trying to trick the typo detection + +template <class T> +class Derived : public Base<T> { +public: + // after-error@+1 {{member initializer 'Base' does not name a non-static data member or base class}} + Derived() : Base() {} // before-warning {{unqualified base initializer of class templates is a Microsoft extension}} +private: + int Baze; // Trying to trick the typo detection +}; + +template <class T> struct AggregateBase { + T i; +}; + +template <class T> +struct AggregateDerived : public AggregateBase<T> { + int i; + + // after-error@+1 {{member initializer 'AggregateBase' does not name a non-static data member or base class}} + AggregateDerived(T j) : AggregateBase{4}, i{j} {} // before-warning {{unqualified base initializer of class templates is a Microsoft extension}} + int f() { + return i + AggregateBase::i; // expected-warning {{use of undeclared identifier 'AggregateBase'; unqualified lookup into dependent bases of class template 'AggregateDerived' is a Microsoft extension}} + } +}; + +template <class T, typename U> struct MultiTypesBase { +}; + +template <class T, class U> +struct MultiTypesDerived : public MultiTypesBase<T, U> { + // after-error@+1 {{member initializer 'MultiTypesBase' does not name a non-static data member or base class}} + MultiTypesDerived() : MultiTypesBase{} {} // before-warning {{unqualified base initializer of class templates is a Microsoft extension}} +}; + +template <int I> struct IntegerBase { +}; + +template <int I> +struct IntegerDerived : public IntegerBase<I> { + // after-error@+1 {{member initializer 'IntegerBase' does not name a non-static data member or base class}} + IntegerDerived() : IntegerBase{} {} // before-warning {{unqualified base initializer of class templates is a Microsoft extension}} +}; + +template <class T> struct ConformingBase { + T i; +}; + +template <class T> +struct ConformingDerived : public ConformingBase<T> { + int i; + + ConformingDerived(T j) : ConformingBase<T>{4}, i{j} {} + int f() { + return i + ConformingBase<T>::i; + } +}; + +int main() { + int I; + Derived<int> t; + + AggregateDerived<int> AD{2}; + AD.AggregateBase::i = 3; + I = AD.f(); + + MultiTypesDerived<int, double> MTD; + + IntegerDerived<4> ID; + + ConformingDerived<int> CD{2}; + I = CD.f(); + + return I; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits