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 T> class A {
public:
  typedef int TYPE;
};
template<class T> class B : public A<T> {
public:
  A<T>::TYPE a; // no typename required because A<T> is a base class.
};

llvm-svn: 129425
This commit is contained in:
Francois Pichet 2011-04-13 02:38:49 +00:00
parent bbe277c4a9
commit 48c946e5ef
4 changed files with 67 additions and 1 deletions

View File

@ -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<CXX0x>;
def err_typename_refers_to_using_value_decl : Error<

View File

@ -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,

View File

@ -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 T> class A {
/// public:
/// typedef int TYPE;
/// };
/// template<class T> class B : public A<T> {
/// public:
/// A<T>::TYPE a; // no typename required because A<T> is a base class.
/// };
/// @endcode
bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) {
if (CurContext->isRecord()) {
const Type* Ty = SS->getScopeRep()->getAsType();
CXXRecordDecl *RD = cast<CXXRecordDecl>(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 ");

View File

@ -136,3 +136,35 @@ public:
template <class T>
void BB<T>::f(int g = 0) { } // expected-warning {{redefinition of default argument}}
namespace MissingTypename {
template<class T> class A {
public:
typedef int TYPE;
};
template<class T> class B {
public:
typedef int TYPE;
};
template<class T, class U>
class C : private A<T>, public B<U> {
public:
typedef A<T> Base1;
typedef B<U> Base2;
typedef A<U> Base3;
A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}}
Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}}
B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}}
Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}}
A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}}
Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}}
};
}