зеркало из https://github.com/microsoft/clang-1.git
In a mem-initializer, a nested-name-specifier followed by an
identifier always names a type. In the case of a dependent nested-name-specifier, build a TypenameType to describe the dependent base type. I'd like to move more of this behavior up into the parser, but this fixes PR6062. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93871 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
e39fe72df7
Коммит
7a886e1a12
|
@ -1062,8 +1062,23 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
|
||||||
if (!TyD) {
|
if (!TyD) {
|
||||||
if (R.isAmbiguous()) return true;
|
if (R.isAmbiguous()) return true;
|
||||||
|
|
||||||
|
if (SS.isSet() && isDependentScopeSpecifier(SS)) {
|
||||||
|
bool NotUnknownSpecialization = false;
|
||||||
|
DeclContext *DC = computeDeclContext(SS, false);
|
||||||
|
if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
|
||||||
|
NotUnknownSpecialization = !Record->hasAnyDependentBases();
|
||||||
|
|
||||||
|
if (!NotUnknownSpecialization) {
|
||||||
|
// When the scope specifier can refer to a member of an unknown
|
||||||
|
// specialization, we take it as a type name.
|
||||||
|
BaseType = CheckTypenameType((NestedNameSpecifier *)SS.getScopeRep(),
|
||||||
|
*MemberOrBase, SS.getRange());
|
||||||
|
R.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If no results were found, try to correct typos.
|
// If no results were found, try to correct typos.
|
||||||
if (R.empty() &&
|
if (R.empty() && BaseType.isNull() &&
|
||||||
CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) {
|
CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) {
|
||||||
if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
|
if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
|
||||||
if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
|
if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
|
||||||
|
@ -1106,20 +1121,22 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TyD) {
|
if (!TyD && BaseType.isNull()) {
|
||||||
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
|
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
|
||||||
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
|
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType = Context.getTypeDeclType(TyD);
|
if (BaseType.isNull()) {
|
||||||
if (SS.isSet()) {
|
BaseType = Context.getTypeDeclType(TyD);
|
||||||
NestedNameSpecifier *Qualifier =
|
if (SS.isSet()) {
|
||||||
static_cast<NestedNameSpecifier*>(SS.getScopeRep());
|
NestedNameSpecifier *Qualifier =
|
||||||
|
static_cast<NestedNameSpecifier*>(SS.getScopeRep());
|
||||||
|
|
||||||
// FIXME: preserve source range information
|
// FIXME: preserve source range information
|
||||||
BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
|
BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,21 @@ template<typename T> struct s1 : s0<typename s0_traits<T>::t0> {
|
||||||
s1() {}
|
s1() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PR6062
|
||||||
|
namespace PR6062 {
|
||||||
|
template <typename T>
|
||||||
|
class A : public T::type
|
||||||
|
{
|
||||||
|
A() : T::type()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
A(U const& init)
|
||||||
|
: T::type(init)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
A(U& init) : U::other_type(init) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче