Account for out-of-line declarations in members_of.
This commit is contained in:
@@ -559,6 +559,11 @@ class NamespaceDecl : public NamedDecl,
|
||||
/// The unnamed namespace that inhabits this namespace, if any.
|
||||
NamespaceDecl *AnonymousNamespace = nullptr;
|
||||
|
||||
/// The most recent Decl whose target scope is this namespace, but whose
|
||||
/// lexical scope is another DeclContext. Used to traverse namespace members
|
||||
/// (i.e., for reflection).
|
||||
Decl *LastMultDCSemaDecl = nullptr;
|
||||
|
||||
protected:
|
||||
NamespaceDecl(Kind K, ASTContext &C, DeclContext *DC, bool Inline,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
@@ -645,6 +650,9 @@ public:
|
||||
NamespaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
|
||||
const NamespaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
|
||||
|
||||
Decl *getLastMultDCSemaDecl() { return LastMultDCSemaDecl; }
|
||||
void setLastMultDCSemaDecl(Decl *D) { LastMultDCSemaDecl = D; }
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange(LocStart, RBraceLoc);
|
||||
}
|
||||
|
||||
@@ -254,6 +254,8 @@ private:
|
||||
struct MultipleDC {
|
||||
DeclContext *SemanticDC;
|
||||
DeclContext *LexicalDC;
|
||||
|
||||
Decl *PrevMultDCSemaDecl;
|
||||
};
|
||||
|
||||
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
|
||||
@@ -448,6 +450,11 @@ public:
|
||||
Decl *getNextDeclInContext() { return NextInContextAndBits.getPointer(); }
|
||||
const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();}
|
||||
|
||||
Decl *getPrevMultDCDeclInSemaContext();
|
||||
const Decl *getPrevMultDCDeclInSemaContext() const {
|
||||
return const_cast<Decl*>(this)->getPrevMultDCDeclInSemaContext();
|
||||
}
|
||||
|
||||
DeclContext *getDeclContext() {
|
||||
if (isInSemaDC())
|
||||
return getSemanticDC();
|
||||
|
||||
@@ -403,6 +403,7 @@ void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
|
||||
auto *MDC = new (Ctx) Decl::MultipleDC();
|
||||
MDC->SemanticDC = SemaDC;
|
||||
MDC->LexicalDC = LexicalDC;
|
||||
MDC->PrevMultDCSemaDecl = nullptr;
|
||||
DeclCtx = MDC;
|
||||
}
|
||||
}
|
||||
@@ -1237,6 +1238,11 @@ bool Decl::isFunctionPointerType() const {
|
||||
return Ty.getCanonicalType()->isFunctionPointerType();
|
||||
}
|
||||
|
||||
Decl *Decl::getPrevMultDCDeclInSemaContext() {
|
||||
assert(!isInSemaDC());
|
||||
return getMultipleDC()->PrevMultDCSemaDecl;
|
||||
}
|
||||
|
||||
DeclContext *Decl::getNonTransparentDeclContext() {
|
||||
assert(getDeclContext());
|
||||
return getDeclContext()->getNonTransparentContext();
|
||||
@@ -1782,6 +1788,14 @@ void DeclContext::addHiddenDecl(Decl *D) {
|
||||
FirstDecl = LastDecl = D;
|
||||
}
|
||||
|
||||
if (auto *NS = dyn_cast<NamespaceDecl>(D->getDeclContext());
|
||||
NS && !D->isInSemaDC()) {
|
||||
NS = NS->getCanonicalDecl();
|
||||
|
||||
D->getMultipleDC()->PrevMultDCSemaDecl = NS->getLastMultDCSemaDecl();
|
||||
NS->setLastMultDCSemaDecl(D);
|
||||
}
|
||||
|
||||
// Notify a C++ record declaration that we've added a member, so it can
|
||||
// update its class-specific state.
|
||||
if (auto *Record = dyn_cast<CXXRecordDecl>(this))
|
||||
|
||||
@@ -1334,7 +1334,16 @@ static bool ensureDeclared(ASTContext &C, QualType QT, SourceLocation SpecLoc) {
|
||||
static bool isReflectableDecl(MetaActions &Meta, ASTContext &C, Decl *D) {
|
||||
assert(D && "null declaration");
|
||||
|
||||
if (D != D->getCanonicalDecl())
|
||||
if (D != D->getCanonicalDecl()) {
|
||||
Decl *First = nullptr;
|
||||
for (Decl *I = D->getMostRecentDecl(); I; I = I->getPreviousDecl())
|
||||
if (I->getLexicalDeclContext() == D->getLexicalDeclContext())
|
||||
First = I;
|
||||
if (D != First)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (D->isLocalExternDecl())
|
||||
return false;
|
||||
|
||||
if (isa<NamespaceAliasDecl>(D))
|
||||
@@ -1355,7 +1364,6 @@ static bool isReflectableDecl(MetaActions &Meta, ASTContext &C, Decl *D) {
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
for (auto *R = FD->getMostRecentDecl(); R; R = R->getPreviousDecl()) {
|
||||
if (!R->getDeclaredReturnType()->isUndeducedType() &&
|
||||
R->getDeclContext() == R->getLexicalDeclContext() &&
|
||||
Meta.HasSatisfiedConstraints(R))
|
||||
return true;
|
||||
}
|
||||
@@ -1386,26 +1394,35 @@ static Decl *findIterableMember(MetaActions &Meta, ASTContext &C, Decl *D,
|
||||
}
|
||||
|
||||
do {
|
||||
DeclContext *DC = D->getDeclContext();
|
||||
DeclContext *DC = D->getDeclContext(); // note: SemanticDC
|
||||
|
||||
// Get the next declaration in the DeclContext.
|
||||
//
|
||||
// Explicit specializations of templates are created with the DeclContext of
|
||||
// the template from which they're instantiated, but they end up in the
|
||||
// DeclContext within which they're declared. We therefore skip over any
|
||||
// declarations whose DeclContext is different from the previous Decl;
|
||||
// otherwise, we may inadvertently break the chain of redeclarations in
|
||||
// difficult to predit ways.
|
||||
do {
|
||||
D = D->getNextDeclInContext();
|
||||
} while (D && D->getDeclContext() != DC);
|
||||
if (D->getLexicalDeclContext() == DC) {
|
||||
// Get the next declaration in the DeclContext.
|
||||
//
|
||||
// Explicit specializations of templates are created with the DeclContext
|
||||
// of the template from which they're instantiated, but they end up in the
|
||||
// DeclContext within which they're declared. We therefore skip over any
|
||||
// declarations whose DeclContext is different from the previous Decl;
|
||||
// otherwise, we may inadvertently break the chain of redeclarations in
|
||||
// difficult to predit ways.
|
||||
do {
|
||||
D = D->getNextDeclInContext();
|
||||
} while (D && D->getDeclContext() != DC);
|
||||
|
||||
// In the case of namespaces, walk the redeclaration chain.
|
||||
if (auto *NSDecl = dyn_cast<NamespaceDecl>(DC)) {
|
||||
while (!D && NSDecl) {
|
||||
NSDecl = NSDecl->getPreviousDecl();
|
||||
D = NSDecl ? *NSDecl->decls_begin() : nullptr;
|
||||
// In the case of namespaces, walk the redeclaration chain.
|
||||
if (auto *NSDecl = dyn_cast<NamespaceDecl>(DC)) {
|
||||
while (!D && NSDecl) {
|
||||
NSDecl = NSDecl->getPreviousDecl();
|
||||
D = NSDecl ? *NSDecl->decls_begin() : nullptr;
|
||||
}
|
||||
|
||||
if (!D) {
|
||||
auto *Canonical = cast<NamespaceDecl>(DC->getPrimaryContext());
|
||||
D = Canonical->getLastMultDCSemaDecl();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
D = D->getPrevMultDCDeclInSemaContext();
|
||||
}
|
||||
|
||||
// We need to recursively descend into LinkageSpecDecls to iterate over the
|
||||
|
||||
@@ -435,6 +435,46 @@ static_assert(members_of(^^NS,
|
||||
|
||||
} // namespace deduced_return_type
|
||||
|
||||
// ========================
|
||||
// out_of_line_declarations
|
||||
// ========================
|
||||
|
||||
namespace out_of_line_declarations {
|
||||
constexpr auto ctx = std::meta::access_context::current();
|
||||
|
||||
namespace NS1 {
|
||||
struct A;
|
||||
|
||||
} // namespace NS1
|
||||
|
||||
struct NS1::A {
|
||||
static void f(class C *);
|
||||
static auto g();
|
||||
};
|
||||
void NS1::A::f(NS1::C *) {}
|
||||
void gq(NS1::C *) {}
|
||||
|
||||
static_assert(
|
||||
*std::ranges::find(
|
||||
[](const auto &r) -> const auto & { return r; }(
|
||||
members_of(^^NS1, ctx)),
|
||||
^^NS1::C) ==
|
||||
^^NS1::C);
|
||||
|
||||
namespace NS2 {
|
||||
namespace Inner {
|
||||
struct S {
|
||||
friend void f();
|
||||
};
|
||||
} // namespace Inner
|
||||
void Inner::f() {}
|
||||
|
||||
} // namespace NS2
|
||||
|
||||
static_assert(1 == members_of(^^NS2, ctx).size());
|
||||
static_assert(2 == members_of(^^NS2::Inner, ctx).size());
|
||||
} // namespace out_of_line_declarations
|
||||
|
||||
int main() {
|
||||
class_members::usage_example();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user