diff options
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-using-decl.cpp | 19 |
2 files changed, 39 insertions, 4 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d87629151e..d0df7fae75 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1558,8 +1558,24 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { } Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { - // The nested name specifier is non-dependent, so no transformation - // is required. The same holds for the name info. + + // The nested name specifier may be dependent, for example + // template <typename T> struct t { + // struct s1 { T f1(); }; + // struct s2 : s1 { using s1::f1; }; + // }; + // template struct t<int>; + // Here, in using s1::f1, s1 refers to t<T>::s1; + // we need to substitute for t<int>::s1. + NestedNameSpecifier *NNS = + SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(), + D->getNestedNameRange(), + TemplateArgs); + if (!NNS) + return 0; + + // The name info is non-dependent, so no transformation + // is required. DeclarationNameInfo NameInfo = D->getNameInfo(); // We only need to do redeclaration lookups if we're in a class @@ -1573,12 +1589,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, D->getNestedNameRange(), D->getUsingLocation(), - D->getTargetNestedNameDecl(), + NNS, NameInfo, D->isTypeName()); CXXScopeSpec SS; - SS.setScopeRep(D->getTargetNestedNameDecl()); + SS.setScopeRep(NNS); SS.setRange(D->getNestedNameRange()); if (CheckRedeclaration) { diff --git a/test/SemaTemplate/instantiate-using-decl.cpp b/test/SemaTemplate/instantiate-using-decl.cpp index 257904490d..1bfcb7a865 100644 --- a/test/SemaTemplate/instantiate-using-decl.cpp +++ b/test/SemaTemplate/instantiate-using-decl.cpp @@ -61,3 +61,22 @@ namespace test2 { template void bar(char *); } + +namespace test3 { + template <typename T> struct t { + struct s1 { + T f1() const; + }; + struct s2 : s1 { + using s1::f1; + T f1() const; + }; + }; + + void f2() + { + t<int>::s2 a; + t<int>::s2 const & b = a; + b.f1(); + } +} |