From daa439a6c47d3299157b94a496bf22389bbc77a3 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 8 Jul 2009 10:57:20 +0000 Subject: [PATCH] Fix a corner case with argument-dependent lookup and overloaded function sets. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74999 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 50 +++++++++++++++++++ lib/AST/DeclCXX.cpp | 33 ++++++++++++ lib/Sema/SemaLookup.cpp | 25 ++++++---- .../basic.lookup.argdep/p2-template-id.cpp | 11 ++++ 4 files changed, 110 insertions(+), 9 deletions(-) diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 741998def1..90c86b17d2 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -132,6 +132,56 @@ public: } static bool classof(const OverloadedFunctionDecl *D) { return true; } }; + +/// \brief Provides uniform iteration syntax for an overload set, function, +/// or function template. +class OverloadIterator { + /// \brief An overloaded function set, function declaration, or + /// function template declaration. + NamedDecl *D; + + /// \brief If the declaration is an overloaded function set, this is the + /// iterator pointing to the current position within that overloaded + /// function set. + OverloadedFunctionDecl::function_iterator Iter; + +public: + typedef AnyFunctionDecl value_type; + typedef value_type reference; + typedef NamedDecl *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + OverloadIterator() : D(0) { } + + OverloadIterator(FunctionDecl *FD) : D(FD) { } + OverloadIterator(FunctionTemplateDecl *FTD) + : D(reinterpret_cast(FTD)) { } + OverloadIterator(OverloadedFunctionDecl *Ovl) + : D(Ovl), Iter(Ovl->function_begin()) { } + + reference operator*() const; + + pointer operator->() const { return (**this).get(); } + + OverloadIterator &operator++(); + + OverloadIterator operator++(int) { + OverloadIterator Temp(*this); + ++(*this); + return Temp; + } + + bool Equals(const OverloadIterator &Other) const; +}; + +inline bool operator==(const OverloadIterator &X, const OverloadIterator &Y) { + return X.Equals(Y); +} + +inline bool operator!=(const OverloadIterator &X, const OverloadIterator &Y) { + return !(X == Y); +} /// CXXBaseSpecifier - A base class of a C++ class. /// diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 6be675ad83..f525667ad0 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -451,6 +451,39 @@ void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) { this->setLocation(F.get()->getLocation()); } +OverloadIterator::reference OverloadIterator::operator*() const { + if (FunctionDecl *FD = dyn_cast(D)) + return FD; + + if (FunctionTemplateDecl *FTD = dyn_cast(D)) + return FTD; + + assert(isa(D)); + return *Iter; +} + +OverloadIterator &OverloadIterator::operator++() { + if (isa(D) || isa(D)) { + D = 0; + return *this; + } + + if (++Iter == cast(D)->function_end()) + D = 0; + + return *this; +} + +bool OverloadIterator::Equals(const OverloadIterator &Other) const { + if (!D || !Other.D) + return D == Other.D; + + if (D != Other.D) + return false; + + return !isa(D) || Iter == Other.Iter; +} + LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 343cbae673..c88321e1a3 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" @@ -1579,18 +1580,24 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // classes and namespaces associated with its (non-dependent) // parameter types and return type. DeclRefExpr *DRE = 0; + TemplateIdRefExpr *TIRE = 0; + Arg = Arg->IgnoreParens(); if (UnaryOperator *unaryOp = dyn_cast(Arg)) { - if (unaryOp->getOpcode() == UnaryOperator::AddrOf) + if (unaryOp->getOpcode() == UnaryOperator::AddrOf) { DRE = dyn_cast(unaryOp->getSubExpr()); - } else + TIRE = dyn_cast(unaryOp->getSubExpr()); + } + } else { DRE = dyn_cast(Arg); - if (!DRE) - continue; - - // FIXME: The declaration might be a FunctionTemplateDecl (by itself) - // or might be buried in a TemplateIdRefExpr. - OverloadedFunctionDecl *Ovl - = dyn_cast(DRE->getDecl()); + TIRE = dyn_cast(Arg); + } + + OverloadedFunctionDecl *Ovl = 0; + if (DRE) + Ovl = dyn_cast(DRE->getDecl()); + else if (TIRE) + Ovl = dyn_cast_or_null( + TIRE->getTemplateName().getAsTemplateDecl()); if (!Ovl) continue; diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp index 525afd89ec..e2c76f9183 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp @@ -14,3 +14,14 @@ namespace N3 { int &ir = f((N2::Y*)0); } } + +int g(void *); +long g(N1::X); + +namespace N1 { + void h(int (*)(void *)); +} + +void test() { + h((&g)); +} -- 2.40.0