mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
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:
parent
bbe277c4a9
commit
48c946e5ef
@ -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<
|
||||
|
@ -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,
|
||||
|
@ -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 ");
|
||||
|
@ -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}}
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user