public:
~DeclContext();
+ // For use when debugging; hasValidDeclKind() will always return true for
+ // a correctly constructed object within its lifetime.
+ bool hasValidDeclKind() const;
+
Decl::Kind getDeclKind() const {
return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
}
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
+ void dumpAsDecl() const;
+ void dumpAsDecl(const ASTContext *Ctx) const;
void dumpDeclContext() const;
void dumpLookups() const;
void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false,
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
+
using namespace clang;
using namespace clang::comments;
+void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
+ NodeDumper.AddChild([=] {
+ if (!DC) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+ // An invalid DeclContext is one for which a dyn_cast() from a DeclContext
+ // pointer to a Decl pointer would fail an assertion or otherwise fall prey
+ // to undefined behavior as a result of an invalid associated DeclKind.
+ // Such invalidity is not supposed to happen of course, but, when it does,
+ // the information provided below is intended to provide some hints about
+ // what might have gone awry.
+ {
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
+ OS << "DeclContext";
+ }
+ NodeDumper.dumpPointer(DC);
+ OS << " <";
+ {
+ ColorScope Color(OS, ShowColors, DeclNameColor);
+ OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();
+ }
+ OS << ">";
+ });
+}
+
void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
NodeDumper.AddChild([=] {
OS << "StoredDeclsMap ";
P.Visit(this);
}
+LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {
+ dumpAsDecl(nullptr);
+}
+
+LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
+ // By design, DeclContext is required to be a base class of some class that
+ // derives from Decl. Thus, it should always be possible to dyn_cast() from
+ // a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()
+ // asserts that to be the case. Since this function is intended for use in a
+ // debugger, it performs an additional check in order to prevent a failed
+ // cast and assertion. If that check fails, then the (invalid) DeclContext
+ // is dumped with an indication of its invalidity.
+ if (hasValidDeclKind()) {
+ const auto *D = cast<Decl>(this);
+ D->dump();
+ } else {
+ // If an ASTContext is not available, a less capable ASTDumper is
+ // constructed for which color diagnostics are, regrettably, disabled.
+ ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,
+ Ctx->getDiagnostics().getShowColors())
+ : ASTDumper(llvm::errs(), /*ShowColors*/ false);
+ P.dumpInvalidDeclContext(this);
+ }
+}
+
LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
dumpLookups(llvm::errs());
}