Skip to content

Commit be75925

Browse files
committed
Fix a corner case with argument-dependent lookup and overloaded function sets.
llvm-svn: 74999
1 parent ed3c80e commit be75925

File tree

4 files changed

+110
-9
lines changed

4 files changed

+110
-9
lines changed

clang/include/clang/AST/DeclCXX.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,56 @@ class OverloadedFunctionDecl : public NamedDecl {
132132
}
133133
static bool classof(const OverloadedFunctionDecl *D) { return true; }
134134
};
135+
136+
/// \brief Provides uniform iteration syntax for an overload set, function,
137+
/// or function template.
138+
class OverloadIterator {
139+
/// \brief An overloaded function set, function declaration, or
140+
/// function template declaration.
141+
NamedDecl *D;
142+
143+
/// \brief If the declaration is an overloaded function set, this is the
144+
/// iterator pointing to the current position within that overloaded
145+
/// function set.
146+
OverloadedFunctionDecl::function_iterator Iter;
147+
148+
public:
149+
typedef AnyFunctionDecl value_type;
150+
typedef value_type reference;
151+
typedef NamedDecl *pointer;
152+
typedef int difference_type;
153+
typedef std::forward_iterator_tag iterator_category;
154+
155+
OverloadIterator() : D(0) { }
156+
157+
OverloadIterator(FunctionDecl *FD) : D(FD) { }
158+
OverloadIterator(FunctionTemplateDecl *FTD)
159+
: D(reinterpret_cast<NamedDecl*>(FTD)) { }
160+
OverloadIterator(OverloadedFunctionDecl *Ovl)
161+
: D(Ovl), Iter(Ovl->function_begin()) { }
162+
163+
reference operator*() const;
164+
165+
pointer operator->() const { return (**this).get(); }
166+
167+
OverloadIterator &operator++();
168+
169+
OverloadIterator operator++(int) {
170+
OverloadIterator Temp(*this);
171+
++(*this);
172+
return Temp;
173+
}
174+
175+
bool Equals(const OverloadIterator &Other) const;
176+
};
177+
178+
inline bool operator==(const OverloadIterator &X, const OverloadIterator &Y) {
179+
return X.Equals(Y);
180+
}
181+
182+
inline bool operator!=(const OverloadIterator &X, const OverloadIterator &Y) {
183+
return !(X == Y);
184+
}
135185

136186
/// CXXBaseSpecifier - A base class of a C++ class.
137187
///

clang/lib/AST/DeclCXX.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,39 @@ void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) {
451451
this->setLocation(F.get()->getLocation());
452452
}
453453

454+
OverloadIterator::reference OverloadIterator::operator*() const {
455+
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
456+
return FD;
457+
458+
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
459+
return FTD;
460+
461+
assert(isa<OverloadedFunctionDecl>(D));
462+
return *Iter;
463+
}
464+
465+
OverloadIterator &OverloadIterator::operator++() {
466+
if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
467+
D = 0;
468+
return *this;
469+
}
470+
471+
if (++Iter == cast<OverloadedFunctionDecl>(D)->function_end())
472+
D = 0;
473+
474+
return *this;
475+
}
476+
477+
bool OverloadIterator::Equals(const OverloadIterator &Other) const {
478+
if (!D || !Other.D)
479+
return D == Other.D;
480+
481+
if (D != Other.D)
482+
return false;
483+
484+
return !isa<OverloadedFunctionDecl>(D) || Iter == Other.Iter;
485+
}
486+
454487
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
455488
DeclContext *DC,
456489
SourceLocation L,

clang/lib/Sema/SemaLookup.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/DeclObjC.h"
2020
#include "clang/AST/DeclTemplate.h"
2121
#include "clang/AST/Expr.h"
22+
#include "clang/AST/ExprCXX.h"
2223
#include "clang/Parse/DeclSpec.h"
2324
#include "clang/Basic/Builtins.h"
2425
#include "clang/Basic/LangOptions.h"
@@ -1579,18 +1580,24 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
15791580
// classes and namespaces associated with its (non-dependent)
15801581
// parameter types and return type.
15811582
DeclRefExpr *DRE = 0;
1583+
TemplateIdRefExpr *TIRE = 0;
1584+
Arg = Arg->IgnoreParens();
15821585
if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) {
1583-
if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
1586+
if (unaryOp->getOpcode() == UnaryOperator::AddrOf) {
15841587
DRE = dyn_cast<DeclRefExpr>(unaryOp->getSubExpr());
1585-
} else
1588+
TIRE = dyn_cast<TemplateIdRefExpr>(unaryOp->getSubExpr());
1589+
}
1590+
} else {
15861591
DRE = dyn_cast<DeclRefExpr>(Arg);
1587-
if (!DRE)
1588-
continue;
1589-
1590-
// FIXME: The declaration might be a FunctionTemplateDecl (by itself)
1591-
// or might be buried in a TemplateIdRefExpr.
1592-
OverloadedFunctionDecl *Ovl
1593-
= dyn_cast<OverloadedFunctionDecl>(DRE->getDecl());
1592+
TIRE = dyn_cast<TemplateIdRefExpr>(Arg);
1593+
}
1594+
1595+
OverloadedFunctionDecl *Ovl = 0;
1596+
if (DRE)
1597+
Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl());
1598+
else if (TIRE)
1599+
Ovl = dyn_cast_or_null<OverloadedFunctionDecl>(
1600+
TIRE->getTemplateName().getAsTemplateDecl());
15941601
if (!Ovl)
15951602
continue;
15961603

clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,14 @@ namespace N3 {
1414
int &ir = f((N2::Y<N1::X>*)0);
1515
}
1616
}
17+
18+
int g(void *);
19+
long g(N1::X);
20+
21+
namespace N1 {
22+
void h(int (*)(void *));
23+
}
24+
25+
void test() {
26+
h((&g));
27+
}

0 commit comments

Comments
 (0)