diff options
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 50 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 25 | ||||
-rw-r--r-- | clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp | 11 |
4 files changed, 110 insertions, 9 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 741998def10..90c86b17d28 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/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<NamedDecl*>(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/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 6be675ad834..f525667ad0a 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/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<FunctionDecl>(D)) + return FD; + + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) + return FTD; + + assert(isa<OverloadedFunctionDecl>(D)); + return *Iter; +} + +OverloadIterator &OverloadIterator::operator++() { + if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { + D = 0; + return *this; + } + + if (++Iter == cast<OverloadedFunctionDecl>(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<OverloadedFunctionDecl>(D) || Iter == Other.Iter; +} + LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 343cbae673a..c88321e1a35 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/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<UnaryOperator>(Arg)) { - if (unaryOp->getOpcode() == UnaryOperator::AddrOf) + if (unaryOp->getOpcode() == UnaryOperator::AddrOf) { DRE = dyn_cast<DeclRefExpr>(unaryOp->getSubExpr()); - } else + TIRE = dyn_cast<TemplateIdRefExpr>(unaryOp->getSubExpr()); + } + } else { DRE = dyn_cast<DeclRefExpr>(Arg); - if (!DRE) - continue; - - // FIXME: The declaration might be a FunctionTemplateDecl (by itself) - // or might be buried in a TemplateIdRefExpr. - OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()); + TIRE = dyn_cast<TemplateIdRefExpr>(Arg); + } + + OverloadedFunctionDecl *Ovl = 0; + if (DRE) + Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()); + else if (TIRE) + Ovl = dyn_cast_or_null<OverloadedFunctionDecl>( + TIRE->getTemplateName().getAsTemplateDecl()); if (!Ovl) continue; diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp index 525afd89ec9..e2c76f91833 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp @@ -14,3 +14,14 @@ namespace N3 { int &ir = f((N2::Y<N1::X>*)0); } } + +int g(void *); +long g(N1::X); + +namespace N1 { + void h(int (*)(void *)); +} + +void test() { + h((&g)); +} |