summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-02 01:30:27 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-02 01:30:27 +0000
commitc5a89a1cc2f168ad0a115c560b8de5f1c952d8c5 (patch)
treef2fa73048310663a8c7025cc852be2dcdc0d78ba
parent651f3d44dbae18c74c5f475d7a601d65b07b45c4 (diff)
Basic semantic analysis support for inheriting constructor declarations in
dependent contexts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153858 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDecl.cpp2
-rw-r--r--lib/Sema/SemaDeclCXX.cpp24
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp6
-rw-r--r--test/CXX/special/class.inhctor/elsewhere.cpp26
-rw-r--r--test/CXX/special/class.inhctor/p3.cpp18
-rw-r--r--test/CXX/special/class.inhctor/p7.cpp13
7 files changed, 76 insertions, 15 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 045b2fa69a..747feaab30 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2978,7 +2978,7 @@ public:
bool IsTypeName,
SourceLocation TypenameLoc);
- bool CheckInheritedConstructorUsingDecl(UsingDecl *UD);
+ bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
Decl *ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 75f7f99efb..9e193bebbe 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 5a64d09bae..c6cd9a2479 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8e4942988d..ba1bc9fd2a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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.
diff --git a/test/CXX/special/class.inhctor/elsewhere.cpp b/test/CXX/special/class.inhctor/elsewhere.cpp
index 60cfff8088..66afa17309 100644
--- a/test/CXX/special/class.inhctor/elsewhere.cpp
+++ b/test/CXX/special/class.inhctor/elsewhere.cpp
@@ -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}}
diff --git a/test/CXX/special/class.inhctor/p3.cpp b/test/CXX/special/class.inhctor/p3.cpp
index 989c17c8b4..f71ab16c0f 100644
--- a/test/CXX/special/class.inhctor/p3.cpp
+++ b/test/CXX/special/class.inhctor/p3.cpp
@@ -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);
+};
diff --git a/test/CXX/special/class.inhctor/p7.cpp b/test/CXX/special/class.inhctor/p7.cpp
index 736754d8a3..9ae160f054 100644
--- a/test/CXX/special/class.inhctor/p7.cpp
+++ b/test/CXX/special/class.inhctor/p7.cpp
@@ -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}}