summaryrefslogtreecommitdiff
path: root/clang/lib/AST/TextNodeDumper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/TextNodeDumper.cpp')
-rw-r--r--clang/lib/AST/TextNodeDumper.cpp407
1 files changed, 343 insertions, 64 deletions
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 965ad17fcfa5..5b0a0ac392c0 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -11,10 +11,19 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/TextNodeDumper.h"
+#include "clang/AST/APValue.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/LocInfoType.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TypeTraits.h"
+
+#include <algorithm>
+#include <utility>
using namespace clang;
@@ -47,12 +56,15 @@ static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
}
-TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors,
- const SourceManager *SM,
- const PrintingPolicy &PrintPolicy,
- const comments::CommandTraits *Traits)
- : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), SM(SM),
- PrintPolicy(PrintPolicy), Traits(Traits) {}
+TextNodeDumper::TextNodeDumper(raw_ostream &OS, const ASTContext &Context,
+ bool ShowColors)
+ : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors),
+ Context(&Context), SM(&Context.getSourceManager()),
+ PrintPolicy(Context.getPrintingPolicy()),
+ Traits(&Context.getCommentCommandTraits()) {}
+
+TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors)
+ : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors) {}
void TextNodeDumper::Visit(const comments::Comment *C,
const comments::FullComment *FC) {
@@ -121,12 +133,14 @@ void TextNodeDumper::Visit(const Stmt *Node) {
dumpPointer(Node);
dumpSourceRange(Node->getSourceRange());
- if (Node->isOMPStructuredBlock())
- OS << " openmp_structured_block";
-
if (const auto *E = dyn_cast<Expr>(Node)) {
dumpType(E->getType());
+ if (E->containsErrors()) {
+ ColorScope Color(OS, ShowColors, ErrorsColor);
+ OS << " contains-errors";
+ }
+
{
ColorScope Color(OS, ShowColors, ValueKindColor);
switch (E->getValueKind()) {
@@ -158,6 +172,9 @@ void TextNodeDumper::Visit(const Stmt *Node) {
case OK_VectorComponent:
OS << " vectorcomponent";
break;
+ case OK_MatrixComponent:
+ OS << " matrixcomponent";
+ break;
}
}
}
@@ -193,6 +210,11 @@ void TextNodeDumper::Visit(const Type *T) {
if (SingleStepDesugar != QualType(T, 0))
OS << " sugar";
+ if (T->containsErrors()) {
+ ColorScope Color(OS, ShowColors, ErrorsColor);
+ OS << " contains-errors";
+ }
+
if (T->isDependentType())
OS << " dependent";
else if (T->isInstantiationDependentType())
@@ -243,7 +265,7 @@ void TextNodeDumper::Visit(const Decl *D) {
const_cast<NamedDecl *>(ND)))
AddChild([=] { OS << "also in " << M->getFullModuleName(); });
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- if (ND->isHidden())
+ if (!ND->isUnconditionallyVisible())
OS << " hidden";
if (D->isImplicit())
OS << " implicit";
@@ -310,7 +332,7 @@ void TextNodeDumper::Visit(const OMPClause *C) {
}
{
ColorScope Color(OS, ShowColors, AttrColor);
- StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
+ StringRef ClauseName(llvm::omp::getOpenMPClauseName(C->getClauseKind()));
OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
<< ClauseName.drop_front() << "Clause";
}
@@ -333,6 +355,218 @@ void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
OS << " selected";
}
+static double GetApproxValue(const llvm::APFloat &F) {
+ llvm::APFloat V = F;
+ bool ignored;
+ V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
+ &ignored);
+ return V.convertToDouble();
+}
+
+/// True if the \p APValue \p Value can be folded onto the current line.
+static bool isSimpleAPValue(const APValue &Value) {
+ switch (Value.getKind()) {
+ case APValue::None:
+ case APValue::Indeterminate:
+ case APValue::Int:
+ case APValue::Float:
+ case APValue::FixedPoint:
+ case APValue::ComplexInt:
+ case APValue::ComplexFloat:
+ case APValue::LValue:
+ case APValue::MemberPointer:
+ case APValue::AddrLabelDiff:
+ return true;
+ case APValue::Vector:
+ case APValue::Array:
+ case APValue::Struct:
+ return false;
+ case APValue::Union:
+ return isSimpleAPValue(Value.getUnionValue());
+ }
+ llvm_unreachable("unexpected APValue kind!");
+}
+
+/// Dump the children of the \p APValue \p Value.
+///
+/// \param[in] Value The \p APValue to visit
+/// \param[in] Ty The \p QualType passed to \p Visit
+///
+/// \param[in] IdxToChildFun A function mapping an \p APValue and an index
+/// to one of the child of the \p APValue
+///
+/// \param[in] NumChildren \p IdxToChildFun will be called on \p Value with
+/// the indices in the range \p [0,NumChildren(
+///
+/// \param[in] LabelSingular The label to use on a line with a single child
+/// \param[in] LabelPlurial The label to use on a line with multiple children
+void TextNodeDumper::dumpAPValueChildren(
+ const APValue &Value, QualType Ty,
+ const APValue &(*IdxToChildFun)(const APValue &, unsigned),
+ unsigned NumChildren, StringRef LabelSingular, StringRef LabelPlurial) {
+ // To save some vertical space we print up to MaxChildrenPerLine APValues
+ // considered to be simple (by isSimpleAPValue) on a single line.
+ constexpr unsigned MaxChildrenPerLine = 4;
+ unsigned I = 0;
+ while (I < NumChildren) {
+ unsigned J = I;
+ while (J < NumChildren) {
+ if (isSimpleAPValue(IdxToChildFun(Value, J)) &&
+ (J - I < MaxChildrenPerLine)) {
+ ++J;
+ continue;
+ }
+ break;
+ }
+
+ J = std::max(I + 1, J);
+
+ // Print [I,J) on a single line.
+ AddChild(J - I > 1 ? LabelPlurial : LabelSingular, [=]() {
+ for (unsigned X = I; X < J; ++X) {
+ Visit(IdxToChildFun(Value, X), Ty);
+ if (X + 1 != J)
+ OS << ", ";
+ }
+ });
+ I = J;
+ }
+}
+
+void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
+ ColorScope Color(OS, ShowColors, ValueKindColor);
+ switch (Value.getKind()) {
+ case APValue::None:
+ OS << "None";
+ return;
+ case APValue::Indeterminate:
+ OS << "Indeterminate";
+ return;
+ case APValue::Int:
+ OS << "Int ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << Value.getInt();
+ }
+ return;
+ case APValue::Float:
+ OS << "Float ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << GetApproxValue(Value.getFloat());
+ }
+ return;
+ case APValue::FixedPoint:
+ OS << "FixedPoint ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << Value.getFixedPoint();
+ }
+ return;
+ case APValue::Vector: {
+ unsigned VectorLength = Value.getVectorLength();
+ OS << "Vector length=" << VectorLength;
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getVectorElt(Index);
+ },
+ VectorLength, "element", "elements");
+ return;
+ }
+ case APValue::ComplexInt:
+ OS << "ComplexInt ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << Value.getComplexIntReal() << " + " << Value.getComplexIntImag()
+ << 'i';
+ }
+ return;
+ case APValue::ComplexFloat:
+ OS << "ComplexFloat ";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << GetApproxValue(Value.getComplexFloatReal()) << " + "
+ << GetApproxValue(Value.getComplexFloatImag()) << 'i';
+ }
+ return;
+ case APValue::LValue:
+ (void)Context;
+ OS << "LValue <todo>";
+ return;
+ case APValue::Array: {
+ unsigned ArraySize = Value.getArraySize();
+ unsigned NumInitializedElements = Value.getArrayInitializedElts();
+ OS << "Array size=" << ArraySize;
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getArrayInitializedElt(Index);
+ },
+ NumInitializedElements, "element", "elements");
+
+ if (Value.hasArrayFiller()) {
+ AddChild("filler", [=] {
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << ArraySize - NumInitializedElements << " x ";
+ }
+ Visit(Value.getArrayFiller(), Ty);
+ });
+ }
+
+ return;
+ }
+ case APValue::Struct: {
+ OS << "Struct";
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getStructBase(Index);
+ },
+ Value.getStructNumBases(), "base", "bases");
+
+ dumpAPValueChildren(
+ Value, Ty,
+ [](const APValue &Value, unsigned Index) -> const APValue & {
+ return Value.getStructField(Index);
+ },
+ Value.getStructNumFields(), "field", "fields");
+
+ return;
+ }
+ case APValue::Union: {
+ OS << "Union";
+ {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ if (const FieldDecl *FD = Value.getUnionField())
+ OS << " ." << *cast<NamedDecl>(FD);
+ }
+ // If the union value is considered to be simple, fold it into the
+ // current line to save some vertical space.
+ const APValue &UnionValue = Value.getUnionValue();
+ if (isSimpleAPValue(UnionValue)) {
+ OS << ' ';
+ Visit(UnionValue, Ty);
+ } else {
+ AddChild([=] { Visit(UnionValue, Ty); });
+ }
+
+ return;
+ }
+ case APValue::MemberPointer:
+ OS << "MemberPointer <todo>";
+ return;
+ case APValue::AddrLabelDiff:
+ OS << "AddrLabelDiff <todo>";
+ return;
+ }
+ llvm_unreachable("Unknown APValue kind!");
+}
+
void TextNodeDumper::dumpPointer(const void *Ptr) {
ColorScope Color(OS, ShowColors, AddressColor);
OS << ' ' << Ptr;
@@ -432,19 +666,27 @@ void TextNodeDumper::dumpName(const NamedDecl *ND) {
}
void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
- switch (AS) {
- case AS_none:
- break;
- case AS_public:
- OS << "public";
- break;
- case AS_protected:
- OS << "protected";
- break;
- case AS_private:
- OS << "private";
- break;
- }
+ const auto AccessSpelling = getAccessSpelling(AS);
+ if (AccessSpelling.empty())
+ return;
+ OS << AccessSpelling;
+}
+
+void TextNodeDumper::dumpCleanupObject(
+ const ExprWithCleanups::CleanupObject &C) {
+ if (auto *BD = C.dyn_cast<BlockDecl *>())
+ dumpDeclRef(BD, "cleanup");
+ else if (auto *CLE = C.dyn_cast<CompoundLiteralExpr *>())
+ AddChild([=] {
+ OS << "cleanup ";
+ {
+ ColorScope Color(OS, ShowColors, StmtColor);
+ OS << CLE->getStmtClassName();
+ }
+ dumpPointer(CLE);
+ });
+ else
+ llvm_unreachable("unexpected cleanup type");
}
void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) {
@@ -687,11 +929,9 @@ void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
}
void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
- if (Node->getResultAPValueKind() != APValue::None) {
- ColorScope Color(OS, ShowColors, ValueColor);
- OS << " ";
- Node->getAPValueResult().dump(OS);
- }
+ if (Node->hasAPValueResult())
+ AddChild("value",
+ [=] { Visit(Node->getAPValueResult(), Node->getType()); });
}
void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
@@ -699,6 +939,14 @@ void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
OS << " adl";
}
+void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) {
+ const char *OperatorSpelling = clang::getOperatorSpelling(Node->getOperator());
+ if (OperatorSpelling)
+ OS << " '" << OperatorSpelling << "'";
+
+ VisitCallExpr(Node);
+}
+
void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
OS << " <";
{
@@ -809,23 +1057,8 @@ void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *Node) {
- switch (Node->getKind()) {
- case UETT_SizeOf:
- OS << " sizeof";
- break;
- case UETT_AlignOf:
- OS << " alignof";
- break;
- case UETT_VecStep:
- OS << " vec_step";
- break;
- case UETT_OpenMPRequiredSimdAlign:
- OS << " __builtin_omp_required_simd_align";
- break;
- case UETT_PreferredAlignOf:
- OS << " __alignof";
- break;
- }
+ OS << " " << getTraitSpelling(Node->getKind());
+
if (Node->isArgumentType())
dumpType(Node->getArgumentType());
}
@@ -939,6 +1172,18 @@ void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
}
}
+void TextNodeDumper::VisitTypeTraitExpr(const TypeTraitExpr *Node) {
+ OS << " " << getTraitSpelling(Node->getTrait());
+}
+
+void TextNodeDumper::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node) {
+ OS << " " << getTraitSpelling(Node->getTrait());
+}
+
+void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
+ OS << " " << getTraitSpelling(Node->getTrait());
+}
+
void TextNodeDumper::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *Node) {
if (const ValueDecl *VD = Node->getExtendingDecl()) {
@@ -949,7 +1194,7 @@ void TextNodeDumper::VisitMaterializeTemporaryExpr(
void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
- dumpDeclRef(Node->getObject(i), "cleanup");
+ dumpCleanupObject(Node->getObject(i));
}
void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
@@ -1065,6 +1310,23 @@ void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
}
+void TextNodeDumper::VisitOMPIteratorExpr(const OMPIteratorExpr *Node) {
+ OS << " ";
+ for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
+ Visit(Node->getIteratorDecl(I));
+ OS << " = ";
+ const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
+ OS << " begin ";
+ Visit(Range.Begin);
+ OS << " end ";
+ Visit(Range.End);
+ if (Range.Step) {
+ OS << " step ";
+ Visit(Range.Step);
+ }
+ }
+}
+
void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
if (T->isSpelledAsLValue())
OS << " written as lvalue reference";
@@ -1201,6 +1463,11 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) {
OS << " decltype(auto)";
if (!T->isDeduced())
OS << " undeduced";
+ if (T->isConstrained()) {
+ dumpDeclRef(T->getTypeConstraintConcept());
+ for (const auto &Arg : T->getTypeConstraintArguments())
+ VisitTemplateArgument(Arg);
+ }
}
void TextNodeDumper::VisitTemplateSpecializationType(
@@ -1402,6 +1669,16 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
OS << " destroyed";
if (D->isParameterPack())
OS << " pack";
+
+ if (D->hasInit()) {
+ const Expr *E = D->getInit();
+ // Only dump the value of constexpr VarDecls for now.
+ if (E && !E->isValueDependent() && D->isConstexpr()) {
+ const APValue *Value = D->evaluateValue();
+ if (Value)
+ AddChild("value", [=] { Visit(*Value, E->getType()); });
+ }
+ }
}
void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) {
@@ -1491,7 +1768,8 @@ void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) {
}
{
ColorScope Color(OS, ShowColors, AttrColor);
- StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
+ StringRef ClauseName(
+ llvm::omp::getOpenMPClauseName(C->getClauseKind()));
OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
<< ClauseName.drop_front() << "Clause";
}
@@ -1624,6 +1902,7 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "CopyAssignment";
}
+ FLAG(hasSimpleCopyAssignment, simple);
FLAG(hasTrivialCopyAssignment, trivial);
FLAG(hasNonTrivialCopyAssignment, non_trivial);
FLAG(hasCopyAssignmentWithConstParam, has_const_param);
@@ -1914,35 +2193,35 @@ void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
OS << " optional";
- ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
- if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
- if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly)
+ ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
+ if (Attrs != ObjCPropertyAttribute::kind_noattr) {
+ if (Attrs & ObjCPropertyAttribute::kind_readonly)
OS << " readonly";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
+ if (Attrs & ObjCPropertyAttribute::kind_assign)
OS << " assign";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite)
+ if (Attrs & ObjCPropertyAttribute::kind_readwrite)
OS << " readwrite";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_retain)
+ if (Attrs & ObjCPropertyAttribute::kind_retain)
OS << " retain";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_copy)
+ if (Attrs & ObjCPropertyAttribute::kind_copy)
OS << " copy";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ if (Attrs & ObjCPropertyAttribute::kind_nonatomic)
OS << " nonatomic";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic)
+ if (Attrs & ObjCPropertyAttribute::kind_atomic)
OS << " atomic";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_weak)
+ if (Attrs & ObjCPropertyAttribute::kind_weak)
OS << " weak";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_strong)
+ if (Attrs & ObjCPropertyAttribute::kind_strong)
OS << " strong";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
+ if (Attrs & ObjCPropertyAttribute::kind_unsafe_unretained)
OS << " unsafe_unretained";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_class)
+ if (Attrs & ObjCPropertyAttribute::kind_class)
OS << " class";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_direct)
+ if (Attrs & ObjCPropertyAttribute::kind_direct)
OS << " direct";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
+ if (Attrs & ObjCPropertyAttribute::kind_getter)
dumpDeclRef(D->getGetterMethodDecl(), "getter");
- if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
+ if (Attrs & ObjCPropertyAttribute::kind_setter)
dumpDeclRef(D->getSetterMethodDecl(), "setter");
}
}