diff options
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 21 | ||||
-rw-r--r-- | clang/test/SemaCXX/using-decl-templates.cpp | 16 |
4 files changed, 57 insertions, 4 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 45e85c0a49f..37a6d68f1be 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1610,7 +1610,7 @@ public: return TargetNestedNameDecl; } - /// isTypeName - Return true if using decl had 'typename'. + /// isTypeName - Return true if using decl has 'typename'. bool isTypeName() const { return IsTypeName; } static UsingDecl *Create(ASTContext &C, DeclContext *DC, @@ -1651,6 +1651,23 @@ class UnresolvedUsingDecl : public NamedDecl { IsTypeName(IsTypeNameArg) { } public: + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + + /// \brief Get target nested name declaration. + NestedNameSpecifier* getTargetNestedNameSpecifier() { + return TargetNestedNameSpecifier; + } + + /// \brief Returns the source location of the target declaration name. + SourceLocation getTargetNameLocation() const { return TargetNameLocation; } + + /// \brief Returns the source location of the target declaration name. + DeclarationName getTargetName() const { return TargetName; } + + bool isTypeName() const { return IsTypeName; } + static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceRange TargetNNR, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 4874c92dece..5d1c059c7ff 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2160,8 +2160,9 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, << NNS << RD->getDeclName(); return 0; } - - LookupContext = cast<RecordType>(Ty)->getDecl(); + + QualType BaseTy = Context.getCanonicalType(QualType(Ty, 0)); + LookupContext = BaseTy->getAs<RecordType>()->getDecl(); } else { // C++0x N2914 [namespace.udecl]p8: // A using-declaration for a class member shall be a member-declaration. diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0bf832f3ebd..4f9fcc3b9e0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -58,7 +58,8 @@ namespace { Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - + Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); + // Base case. FIXME: Remove once we can instantiate everything. Decl *VisitDecl(Decl *) { assert(false && "Template instantiation of unknown declaration kind!"); @@ -740,6 +741,24 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( return Inst; } +Decl * +TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { + NestedNameSpecifier *NNS = + SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), + D->getTargetNestedNameRange(), + TemplateArgs); + if (!NNS) + return 0; + + CXXScopeSpec SS; + SS.setRange(D->getTargetNestedNameRange()); + SS.setScopeRep(NNS); + + return SemaRef.BuildUsingDeclaration(D->getLocation(), SS, + D->getTargetNameLocation(), + D->getTargetName(), 0, D->isTypeName()); +} + Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, const TemplateArgumentList &TemplateArgs) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); diff --git a/clang/test/SemaCXX/using-decl-templates.cpp b/clang/test/SemaCXX/using-decl-templates.cpp new file mode 100644 index 00000000000..13ee1b2dd3e --- /dev/null +++ b/clang/test/SemaCXX/using-decl-templates.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> struct A { + void f() { } + struct N { }; +}; + +template<typename T> struct B : A<T> { + using A<T>::f; + using A<T>::N; + + using A<T>::foo; // expected-error{{no member named 'foo'}} + using A<double>::f; // expected-error{{using declaration refers into 'A<double>::', which is not a base class of 'B'}} +}; + +B<int> a; // expected-note{{in instantiation of template class 'struct B<int>' requested here}} |