diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 37 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 28 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-using-decl.cpp | 17 |
5 files changed, 98 insertions, 9 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 02a002b452..5021655f33 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -44,16 +44,18 @@ namespace clang { class TargetInfo; // Decls class Decl; + class FieldDecl; + class ObjCIvarDecl; + class ObjCIvarRefExpr; class ObjCPropertyDecl; class RecordDecl; class TagDecl; + class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; class TypedefDecl; - class TemplateTypeParmDecl; - class FieldDecl; - class ObjCIvarRefExpr; - class ObjCIvarDecl; + class UnresolvedUsingDecl; + class UsingDecl; namespace Builtin { class Context; } @@ -171,6 +173,29 @@ class ASTContext { /// class template X). llvm::DenseMap<VarDecl *, VarDecl *> InstantiatedFromStaticDataMember; + /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls + /// where created during instantiation. + /// + /// For example: + /// \code + /// template<typename T> + /// struct A { + /// void f(); + /// }; + /// + /// template<typename T> + /// struct B : A<T> { + /// using A<T>::f; + /// }; + /// + /// template struct B<int>; + /// \endcode + /// + /// This mapping will contain an entry that maps from the UsingDecl in + /// B<int> to the UnresolvedUsingDecl in B<T>. + llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *> + InstantiatedFromUnresolvedUsingDecl; + TranslationUnitDecl *TUDecl; /// SourceMgr - The associated SourceManager object. @@ -242,6 +267,10 @@ public: /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl); + UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); + void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, + UnresolvedUsingDecl *UUD); + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } const char *getCommentForDecl(const Decl *D); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f527657626..eebb11da99 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -242,6 +242,24 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl) { InstantiatedFromStaticDataMember[Inst] = Tmpl; } +UnresolvedUsingDecl * +ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) { + llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>::iterator Pos + = InstantiatedFromUnresolvedUsingDecl.find(UUD); + if (Pos == InstantiatedFromUnresolvedUsingDecl.end()) + return 0; + + return Pos->second; +} + +void +ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, + UnresolvedUsingDecl *UUD) { + assert(!InstantiatedFromUnresolvedUsingDecl[UD] && + "Already noted what using decl what instantiated from"); + InstantiatedFromUnresolvedUsingDecl[UD] = UUD; +} + namespace { class BeforeInTranslationUnit : std::binary_function<SourceRange, SourceRange, bool> { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 521394b978..b1cc328a2d 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -477,6 +477,11 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { if (!InstD) return SemaRef.ExprError(); + // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl, + // we need to get the underlying decl. + // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this? + InstD = InstD->getUnderlyingDecl(); + // FIXME: nested-name-specifier for QualifiedDeclRefExpr return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, /*FIXME:*/false, @@ -685,6 +690,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Invalid = true; else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) Fields.push_back(DeclPtrTy::make(Field)); + else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember)) + Instantiation->addDecl(UD); } else { // FIXME: Eventually, a NULL return will mean that one of the // instantiations was a semantic disaster, and we'll want to set Invalid = diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6c1f0115b6..5978dae311 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -757,9 +757,14 @@ TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { SS.setRange(D->getTargetNestedNameRange()); SS.setScopeRep(NNS); - return SemaRef.BuildUsingDeclaration(D->getLocation(), SS, - D->getTargetNameLocation(), - D->getTargetName(), 0, D->isTypeName()); + NamedDecl *UD = + SemaRef.BuildUsingDeclaration(D->getLocation(), SS, + D->getTargetNameLocation(), + D->getTargetName(), 0, D->isTypeName()); + if (UD) + SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD), + D); + return UD; } Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, @@ -1220,6 +1225,12 @@ static bool isInstantiationOf(EnumDecl *Pattern, return false; } +static bool isInstantiationOf(UnresolvedUsingDecl *Pattern, + UsingDecl *Instance, + ASTContext &C) { + return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern; +} + static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, VarDecl *Instance) { assert(Instance->isStaticDataMember()); @@ -1236,9 +1247,16 @@ static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, } static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { - if (D->getKind() != Other->getKind()) - return false; + if (D->getKind() != Other->getKind()) { + if (UnresolvedUsingDecl *UUD = dyn_cast<UnresolvedUsingDecl>(D)) { + if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { + return isInstantiationOf(UUD, UD, Ctx); + } + } + return false; + } + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other)) return isInstantiationOf(cast<CXXRecordDecl>(D), Record); diff --git a/test/SemaTemplate/instantiate-using-decl.cpp b/test/SemaTemplate/instantiate-using-decl.cpp new file mode 100644 index 0000000000..fd9010fa4b --- /dev/null +++ b/test/SemaTemplate/instantiate-using-decl.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +struct A { + void f(); +}; + +template<typename T> +struct B : A<T> { + using A<T>::f; + + void g() { + f(); + } +}; + +template struct B<int>; |