forked from OSchip/llvm-project
Basic semantic analysis support for inheriting constructor declarations in
dependent contexts. llvm-svn: 153858
This commit is contained in:
parent
7a2cea1814
commit
23d55873cb
|
@ -2978,7 +2978,7 @@ public:
|
|||
bool IsTypeName,
|
||||
SourceLocation TypenameLoc);
|
||||
|
||||
bool CheckInheritedConstructorUsingDecl(UsingDecl *UD);
|
||||
bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
|
||||
|
||||
Decl *ActOnUsingDeclaration(Scope *CurScope,
|
||||
AccessSpecifier AS,
|
||||
|
|
|
@ -118,7 +118,7 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
|
|||
//
|
||||
// We therefore do not perform any name lookup if the result would
|
||||
// refer to a member of an unknown specialization.
|
||||
if (!isClassName)
|
||||
if (!isClassName && !IsCtorOrDtorName)
|
||||
return ParsedType();
|
||||
|
||||
// We know from the grammar that this name refers to a type,
|
||||
|
|
|
@ -6290,9 +6290,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
|
|||
return UD;
|
||||
}
|
||||
|
||||
// Constructor inheriting using decls get special treatment.
|
||||
// The normal rules do not apply to inheriting constructor declarations.
|
||||
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
|
||||
if (CheckInheritedConstructorUsingDecl(UD))
|
||||
if (CheckInheritingConstructorUsingDecl(UD))
|
||||
UD->setInvalidDecl();
|
||||
return UD;
|
||||
}
|
||||
|
@ -6362,11 +6362,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
|
|||
}
|
||||
|
||||
/// Additional checks for a using declaration referring to a constructor name.
|
||||
bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
|
||||
if (UD->isTypeName()) {
|
||||
// FIXME: Cannot specify typename when specifying constructor
|
||||
return true;
|
||||
}
|
||||
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
|
||||
assert(!UD->isTypeName() && "expecting a constructor name");
|
||||
|
||||
const Type *SourceType = UD->getQualifier()->getAsType();
|
||||
assert(SourceType &&
|
||||
|
@ -6381,6 +6378,8 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
|
|||
CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified();
|
||||
if (CanonicalSourceType == BaseType)
|
||||
break;
|
||||
if (BaseIt->getType()->isDependentType())
|
||||
break;
|
||||
}
|
||||
|
||||
if (BaseIt == BaseE) {
|
||||
|
@ -6392,7 +6391,8 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
|
|||
return true;
|
||||
}
|
||||
|
||||
BaseIt->setInheritConstructors();
|
||||
if (!CurContext->isDependentContext())
|
||||
BaseIt->setInheritConstructors();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -7041,7 +7041,6 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
|
|||
Context.getCanonicalType(CtorIt->getType()).getTypePtr());
|
||||
}
|
||||
|
||||
Scope *S = getScopeForContext(ClassDecl);
|
||||
DeclarationName CreatedCtorName =
|
||||
Context.DeclarationNames.getCXXConstructorName(
|
||||
ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified());
|
||||
|
@ -7063,10 +7062,12 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
|
|||
CtorE = BaseDecl->ctor_end();
|
||||
CtorIt != CtorE; ++CtorIt) {
|
||||
// Find the using declaration for inheriting this base's constructors.
|
||||
// FIXME: Don't perform name lookup just to obtain a source location!
|
||||
DeclarationName Name =
|
||||
Context.DeclarationNames.getCXXConstructorName(CanonicalBase);
|
||||
UsingDecl *UD = dyn_cast_or_null<UsingDecl>(
|
||||
LookupSingleName(S, Name,SourceLocation(), LookupUsingDeclName));
|
||||
LookupResult Result(*this, Name, SourceLocation(), LookupUsingDeclName);
|
||||
LookupQualifiedName(Result, CurContext);
|
||||
UsingDecl *UD = Result.getAsSingle<UsingDecl>();
|
||||
SourceLocation UsingLoc = UD ? UD->getLocation() :
|
||||
ClassDecl->getLocation();
|
||||
|
||||
|
@ -7177,7 +7178,6 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
|
|||
NewCtor->setParams(ParamDecls);
|
||||
NewCtor->setInheritedConstructor(BaseCtor);
|
||||
|
||||
PushOnScopeChains(NewCtor, S, false);
|
||||
ClassDecl->addDecl(NewCtor);
|
||||
result.first->second.second = NewCtor;
|
||||
}
|
||||
|
|
|
@ -1856,6 +1856,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
|
|||
if (NewUD->isInvalidDecl())
|
||||
return NewUD;
|
||||
|
||||
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
|
||||
if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD))
|
||||
NewUD->setInvalidDecl();
|
||||
return NewUD;
|
||||
}
|
||||
|
||||
bool isFunctionScope = Owner->isFunctionOrMethod();
|
||||
|
||||
// Process the shadow decls.
|
||||
|
|
|
@ -29,3 +29,29 @@ struct I1 : B1 {
|
|||
struct D1 : I1 {
|
||||
using B1::B1; // expected-error {{'B1' is not a direct base of 'D1', can not inherit constructors}}
|
||||
};
|
||||
|
||||
template<typename T> struct A {};
|
||||
|
||||
template<typename T> struct B : A<bool>, A<char> {
|
||||
using A<T>::A; // expected-error {{'A<double>::', which is not a base class of 'B<double>'}}
|
||||
};
|
||||
B<bool> bb;
|
||||
B<char> bc;
|
||||
B<double> bd; // expected-note {{here}}
|
||||
|
||||
template<typename T> struct C : A<T> {
|
||||
using A<bool>::A; // expected-error {{'A<bool>::', which is not a base class of 'C<char>'}}
|
||||
};
|
||||
C<bool> cb;
|
||||
C<char> cc; // expected-note {{here}}
|
||||
|
||||
template<typename T> struct D : A<T> {};
|
||||
template<typename T> struct E : D<T> {
|
||||
using A<bool>::A; // expected-error {{'A<bool>' is not a direct base of 'E<bool>', can not inherit}}
|
||||
};
|
||||
E<bool> eb; // expected-note {{here}}
|
||||
|
||||
template<typename T> struct F : D<bool> {
|
||||
using A<T>::A; // expected-error {{'A<bool>' is not a direct base of 'F<bool>'}}
|
||||
};
|
||||
F<bool> fb; // expected-note {{here}}
|
||||
|
|
|
@ -28,3 +28,21 @@ struct D3 : B3 { // expected-note 2 {{candidate constructor}}
|
|||
using B3::B3; // expected-note {{candidate constructor (inherited)}}
|
||||
};
|
||||
D3 fd3() { return 1; } // expected-error {{no viable conversion}}
|
||||
|
||||
template<typename T> struct T1 : B1 {
|
||||
using B1::B1;
|
||||
};
|
||||
template<typename T> struct T2 : T1<T> {
|
||||
using T1<int>::T1;
|
||||
};
|
||||
template<typename T> struct T3 : T1<int> {
|
||||
using T1<T>::T1;
|
||||
};
|
||||
struct U {
|
||||
friend T1<int>::T1(int);
|
||||
friend T1<int>::T1(int, int);
|
||||
friend T2<int>::T2(int);
|
||||
friend T2<int>::T2(int, int);
|
||||
friend T3<int>::T3(int);
|
||||
friend T3<int>::T3(int, int);
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// Straight from the standard
|
||||
struct B1 {
|
||||
B1(int); // expected-note {{previous constructor}}
|
||||
B1(int); // expected-note {{previous constructor}} expected-note {{conflicting constructor}}
|
||||
};
|
||||
struct B2 {
|
||||
B2(int); // expected-note {{conflicting constructor}}
|
||||
|
@ -16,3 +16,14 @@ struct D2 : B1, B2 {
|
|||
using B2::B2;
|
||||
D2(int);
|
||||
};
|
||||
|
||||
template<typename T> struct B3 {
|
||||
B3(T); // expected-note {{previous constructor}}
|
||||
};
|
||||
template<typename T> struct B4 : B3<T>, B1 {
|
||||
B4();
|
||||
using B3<T>::B3; // expected-note {{inherited here}}
|
||||
using B1::B1; // expected-error {{already inherited}}
|
||||
};
|
||||
B4<char> b4c;
|
||||
B4<int> b4i; // expected-note {{here}}
|
||||
|
|
Loading…
Reference in New Issue