From: Francois Pichet Date: Wed, 13 Apr 2011 02:38:49 +0000 (+0000) Subject: In Microsoft mode, within class scope, if a CXXScopeSpec's type is equal to the type... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6943e9befee204becfae55de1298b3d5fee87934;p=clang In Microsoft mode, within class scope, if a CXXScopeSpec's type is equal to the type of one of the base classes then downgrade the missing typename error to a warning. Up to now this is the only case I found where MSVC doesn't require "typename" at class scope. Really strange! This fixes 1 error when parsing the MSVC 2008 header files. Example: template class A { public: typedef int TYPE; }; template class B : public A { public: A::TYPE a; // no typename required because A is a base class. }; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129425 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1bdcb88445..9d0c2c4f24 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1946,6 +1946,8 @@ def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; +def war_typename_missing : ExtWarn< + "missing 'typename' prior to dependent type name '%0%1'">; def ext_typename_outside_of_template : ExtWarn< "'typename' occurs outside of a template">, InGroup; def err_typename_refers_to_using_value_decl : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index e931fb6603..1169b50f85 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -799,6 +799,7 @@ public: ParsedType ObjectType = ParsedType(), bool WantNontrivialTypeSourceInfo = false); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); + bool isMicrosoftMissingTypename(const CXXScopeSpec *SS); bool DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a2249c787b..4338ddaa1a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -250,6 +250,33 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { return DeclSpec::TST_unspecified; } +/// isMicrosoftMissingTypename - In Microsoft mode, within class scope, +/// if a CXXScopeSpec's type is equal to the type of one of the base classes +/// then downgrade the missing typename error to a warning. +/// This is needed for MSVC compatibility; Example: +/// @code +/// template class A { +/// public: +/// typedef int TYPE; +/// }; +/// template class B : public A { +/// public: +/// A::TYPE a; // no typename required because A is a base class. +/// }; +/// @endcode +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { + if (CurContext->isRecord()) { + const Type* Ty = SS->getScopeRep()->getAsType(); + + CXXRecordDecl *RD = cast(CurContext); + for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), + BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) + if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) + return true; + } + return false; +} + bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, @@ -327,7 +354,11 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(IILoc, diag::err_typename_nested_not_found) << &II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { - Diag(SS->getRange().getBegin(), diag::err_typename_missing) + unsigned DiagID = diag::err_typename_missing; + if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS)) + DiagID = diag::war_typename_missing; + + Diag(SS->getRange().getBegin(), DiagID) << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 2287d26fa8..c2a32b4c40 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -136,3 +136,35 @@ public: template void BB::f(int g = 0) { } // expected-warning {{redefinition of default argument}} + +namespace MissingTypename { + +template class A { +public: + typedef int TYPE; +}; + +template class B { +public: + typedef int TYPE; +}; + + +template +class C : private A, public B { +public: + typedef A Base1; + typedef B Base2; + typedef A Base3; + + A::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}} + Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}} + + B::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}} + Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}} + + A::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}} + Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}} + }; + +} \ No newline at end of file