[clang] 4247cdb - [clang]: Add DeclContext::dumpAsDecl().
Tom Honermann via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 3 14:26:10 PDT 2022
Author: Tom Honermann
Date: 2022-10-03T17:25:44-04:00
New Revision: 4247cdb568eca4c31b14d91105fe5ee140225036
URL: https://github.com/llvm/llvm-project/commit/4247cdb568eca4c31b14d91105fe5ee140225036
DIFF: https://github.com/llvm/llvm-project/commit/4247cdb568eca4c31b14d91105fe5ee140225036.diff
LOG: [clang]: Add DeclContext::dumpAsDecl().
This change enables a declaration to be conveniently displayed within
a debugger when only a pointer to its DeclContext is available. For example,
in gdb:
(gdb) p Ctx
$1 = (const clang::DeclContext *) 0x14c1a580
(gdb) p Ctx->dumpAsDecl()
ClassTemplateSpecializationDecl 0x14c1a540 <t.cpp:1:1, line:7:1> line:2:8 struct ct
`-TemplateArgument type 'int'
`-BuiltinType 0x14bac420 'int'
$2 = void
In the event that the pointed to DeclContext is invalid (that it has an
invalid DeclKind as a result of a dangling pointer, memory corruption, etc...)
it is not possible to dump its associated declaration. In this case, the
DeclContext will be reported as invalid. For example, in gdb:
(gdb) p Ctx->dumpAsDecl()
DeclContext 0x14c1a580 <unrecognized Decl kind 127>
$3 = void
Added:
Modified:
clang/include/clang/AST/ASTDumper.h
clang/include/clang/AST/DeclBase.h
clang/lib/AST/ASTDumper.cpp
clang/lib/AST/DeclBase.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTDumper.h b/clang/include/clang/AST/ASTDumper.h
index a154bc2db3a7..71ac467e5104 100644
--- a/clang/include/clang/AST/ASTDumper.h
+++ b/clang/include/clang/AST/ASTDumper.h
@@ -32,6 +32,7 @@ class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> {
TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
+ void dumpInvalidDeclContext(const DeclContext *DC);
void dumpLookups(const DeclContext *DC, bool DumpDecls);
template <typename SpecializationDecl>
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 1332b00232be..8a5f75573095 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1909,6 +1909,10 @@ class DeclContext {
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);
}
@@ -2530,6 +2534,8 @@ class DeclContext {
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,
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 60700f71c4b9..9900efb5a48d 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -19,9 +19,37 @@
#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 ";
@@ -200,6 +228,31 @@ LLVM_DUMP_METHOD void Decl::dumpColor() const {
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());
}
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index e06235392af8..a9ac441092be 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -152,6 +152,15 @@ void Decl::setInvalidDecl(bool Invalid) {
}
}
+bool DeclContext::hasValidDeclKind() const {
+ switch (getDeclKind()) {
+#define DECL(DERIVED, BASE) case Decl::DERIVED: return true;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+ return false;
+}
+
const char *DeclContext::getDeclKindName() const {
switch (getDeclKind()) {
#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
More information about the cfe-commits
mailing list