llvm-capstone/clang/lib/AST/StmtDumper.cpp
Ted Kremenek e65b086e07 Add clang support for new Objective-C literal syntax for NSDictionary, NSArray,
NSNumber, and boolean literals.  This includes both Sema and Codegen support.
Included is also support for new Objective-C container subscripting.

My apologies for the large patch.  It was very difficult to break apart.
The patch introduces changes to the driver as well to cause clang to link
in additional runtime support when needed to support the new language features.

Docs are forthcoming to document the implementation and behavior of these features.

llvm-svn: 152137
2012-03-06 20:05:56 +00:00

753 lines
22 KiB
C++

//===--- StmtDumper.cpp - Dumping implementation for Stmt ASTs ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Stmt::dump/Stmt::print methods, which dump out the
// AST in a form that exposes type details and other fields.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// StmtDumper Visitor
//===----------------------------------------------------------------------===//
namespace {
class StmtDumper : public StmtVisitor<StmtDumper> {
SourceManager *SM;
raw_ostream &OS;
unsigned IndentLevel;
/// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump
/// the first few levels of an AST. This keeps track of how many ast levels
/// are left.
unsigned MaxDepth;
/// LastLocFilename/LastLocLine - Keep track of the last location we print
/// out so that we can print out deltas from then on out.
const char *LastLocFilename;
unsigned LastLocLine;
public:
StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth)
: SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) {
LastLocFilename = "";
LastLocLine = ~0U;
}
void DumpSubTree(Stmt *S) {
// Prune the recursion if not using dump all.
if (MaxDepth == 0) return;
++IndentLevel;
if (S) {
if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
VisitDeclStmt(DS);
else {
Visit(S);
// Print out children.
Stmt::child_range CI = S->children();
if (CI) {
while (CI) {
OS << '\n';
DumpSubTree(*CI++);
}
}
}
OS << ')';
} else {
Indent();
OS << "<<<NULL>>>";
}
--IndentLevel;
}
void DumpDeclarator(Decl *D);
void Indent() const {
for (int i = 0, e = IndentLevel; i < e; ++i)
OS << " ";
}
void DumpType(QualType T) {
SplitQualType T_split = T.split();
OS << "'" << QualType::getAsString(T_split) << "'";
if (!T.isNull()) {
// If the type is sugared, also dump a (shallow) desugared type.
SplitQualType D_split = T.getSplitDesugaredType();
if (T_split != D_split)
OS << ":'" << QualType::getAsString(D_split) << "'";
}
}
void DumpDeclRef(Decl *node);
void DumpStmt(const Stmt *Node) {
Indent();
OS << "(" << Node->getStmtClassName()
<< " " << (void*)Node;
DumpSourceRange(Node);
}
void DumpValueKind(ExprValueKind K) {
switch (K) {
case VK_RValue: break;
case VK_LValue: OS << " lvalue"; break;
case VK_XValue: OS << " xvalue"; break;
}
}
void DumpObjectKind(ExprObjectKind K) {
switch (K) {
case OK_Ordinary: break;
case OK_BitField: OS << " bitfield"; break;
case OK_ObjCProperty: OS << " objcproperty"; break;
case OK_ObjCSubscript: OS << " objcsubscript"; break;
case OK_VectorComponent: OS << " vectorcomponent"; break;
}
}
void DumpExpr(const Expr *Node) {
DumpStmt(Node);
OS << ' ';
DumpType(Node->getType());
DumpValueKind(Node->getValueKind());
DumpObjectKind(Node->getObjectKind());
}
void DumpSourceRange(const Stmt *Node);
void DumpLocation(SourceLocation Loc);
// Stmts.
void VisitStmt(Stmt *Node);
void VisitDeclStmt(DeclStmt *Node);
void VisitLabelStmt(LabelStmt *Node);
void VisitGotoStmt(GotoStmt *Node);
// Exprs
void VisitExpr(Expr *Node);
void VisitCastExpr(CastExpr *Node);
void VisitDeclRefExpr(DeclRefExpr *Node);
void VisitPredefinedExpr(PredefinedExpr *Node);
void VisitCharacterLiteral(CharacterLiteral *Node);
void VisitIntegerLiteral(IntegerLiteral *Node);
void VisitFloatingLiteral(FloatingLiteral *Node);
void VisitStringLiteral(StringLiteral *Str);
void VisitUnaryOperator(UnaryOperator *Node);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node);
void VisitMemberExpr(MemberExpr *Node);
void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
void VisitBinaryOperator(BinaryOperator *Node);
void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
void VisitAddrLabelExpr(AddrLabelExpr *Node);
void VisitBlockExpr(BlockExpr *Node);
void VisitOpaqueValueExpr(OpaqueValueExpr *Node);
// C++
void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
void VisitCXXThisExpr(CXXThisExpr *Node);
void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
void VisitCXXConstructExpr(CXXConstructExpr *Node);
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node);
void VisitExprWithCleanups(ExprWithCleanups *Node);
void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node);
void DumpCXXTemporary(CXXTemporary *Temporary);
// ObjC
void VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node);
void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
void VisitObjCMessageExpr(ObjCMessageExpr* Node);
void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node);
};
}
//===----------------------------------------------------------------------===//
// Utilities
//===----------------------------------------------------------------------===//
void StmtDumper::DumpLocation(SourceLocation Loc) {
SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
// The general format we print out is filename:line:col, but we drop pieces
// that haven't changed since the last loc printed.
PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
if (PLoc.isInvalid()) {
OS << "<invalid sloc>";
return;
}
if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
OS << PLoc.getFilename() << ':' << PLoc.getLine()
<< ':' << PLoc.getColumn();
LastLocFilename = PLoc.getFilename();
LastLocLine = PLoc.getLine();
} else if (PLoc.getLine() != LastLocLine) {
OS << "line" << ':' << PLoc.getLine()
<< ':' << PLoc.getColumn();
LastLocLine = PLoc.getLine();
} else {
OS << "col" << ':' << PLoc.getColumn();
}
}
void StmtDumper::DumpSourceRange(const Stmt *Node) {
// Can't translate locations if a SourceManager isn't available.
if (SM == 0) return;
// TODO: If the parent expression is available, we can print a delta vs its
// location.
SourceRange R = Node->getSourceRange();
OS << " <";
DumpLocation(R.getBegin());
if (R.getBegin() != R.getEnd()) {
OS << ", ";
DumpLocation(R.getEnd());
}
OS << ">";
// <t2.c:123:421[blah], t2.c:412:321>
}
//===----------------------------------------------------------------------===//
// Stmt printing methods.
//===----------------------------------------------------------------------===//
void StmtDumper::VisitStmt(Stmt *Node) {
DumpStmt(Node);
}
void StmtDumper::DumpDeclarator(Decl *D) {
// FIXME: Need to complete/beautify this... this code simply shows the
// nodes are where they need to be.
if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
OS << "\"typedef " << localType->getUnderlyingType().getAsString()
<< ' ' << *localType << '"';
} else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) {
OS << "\"using " << *localType << " = "
<< localType->getUnderlyingType().getAsString() << '"';
} else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
OS << "\"";
// Emit storage class for vardecls.
if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
if (V->getStorageClass() != SC_None)
OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass())
<< " ";
}
std::string Name = VD->getNameAsString();
VD->getType().getAsStringInternal(Name,
PrintingPolicy(VD->getASTContext().getLangOptions()));
OS << Name;
// If this is a vardecl with an initializer, emit it.
if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
if (V->getInit()) {
OS << " =\n";
DumpSubTree(V->getInit());
}
}
OS << '"';
} else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
// print a free standing tag decl (e.g. "struct x;").
const char *tagname;
if (const IdentifierInfo *II = TD->getIdentifier())
tagname = II->getNameStart();
else
tagname = "<anonymous>";
OS << '"' << TD->getKindName() << ' ' << tagname << ";\"";
// FIXME: print tag bodies.
} else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) {
// print using-directive decl (e.g. "using namespace x;")
const char *ns;
if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
ns = II->getNameStart();
else
ns = "<anonymous>";
OS << '"' << UD->getDeclKindName() << ns << ";\"";
} else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
// print using decl (e.g. "using std::string;")
const char *tn = UD->isTypeName() ? "typename " : "";
OS << '"' << UD->getDeclKindName() << tn;
UD->getQualifier()->print(OS,
PrintingPolicy(UD->getASTContext().getLangOptions()));
OS << ";\"";
} else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
OS << "label " << *LD;
} else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) {
OS << "\"static_assert(\n";
DumpSubTree(SAD->getAssertExpr());
OS << ",\n";
DumpSubTree(SAD->getMessage());
OS << ");\"";
} else {
llvm_unreachable("Unexpected decl");
}
}
void StmtDumper::VisitDeclStmt(DeclStmt *Node) {
DumpStmt(Node);
OS << "\n";
for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
DI != DE; ++DI) {
Decl* D = *DI;
++IndentLevel;
Indent();
OS << (void*) D << " ";
DumpDeclarator(D);
if (DI+1 != DE)
OS << "\n";
--IndentLevel;
}
}
void StmtDumper::VisitLabelStmt(LabelStmt *Node) {
DumpStmt(Node);
OS << " '" << Node->getName() << "'";
}
void StmtDumper::VisitGotoStmt(GotoStmt *Node) {
DumpStmt(Node);
OS << " '" << Node->getLabel()->getName()
<< "':" << (void*)Node->getLabel();
}
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
void StmtDumper::VisitExpr(Expr *Node) {
DumpExpr(Node);
}
static void DumpBasePath(raw_ostream &OS, CastExpr *Node) {
if (Node->path_empty())
return;
OS << " (";
bool First = true;
for (CastExpr::path_iterator
I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
const CXXBaseSpecifier *Base = *I;
if (!First)
OS << " -> ";
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (Base->isVirtual())
OS << "virtual ";
OS << RD->getName();
First = false;
}
OS << ')';
}
void StmtDumper::VisitCastExpr(CastExpr *Node) {
DumpExpr(Node);
OS << " <" << Node->getCastKindName();
DumpBasePath(OS, Node);
OS << ">";
}
void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
DumpExpr(Node);
OS << " ";
DumpDeclRef(Node->getDecl());
if (Node->getDecl() != Node->getFoundDecl()) {
OS << " (";
DumpDeclRef(Node->getFoundDecl());
OS << ")";
}
}
void StmtDumper::DumpDeclRef(Decl *d) {
OS << d->getDeclKindName() << ' ' << (void*) d;
if (NamedDecl *nd = dyn_cast<NamedDecl>(d)) {
OS << " '";
nd->getDeclName().printName(OS);
OS << "'";
}
if (ValueDecl *vd = dyn_cast<ValueDecl>(d)) {
OS << ' '; DumpType(vd->getType());
}
}
void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
DumpExpr(Node);
OS << " (";
if (!Node->requiresADL()) OS << "no ";
OS << "ADL) = '" << Node->getName() << '\'';
UnresolvedLookupExpr::decls_iterator
I = Node->decls_begin(), E = Node->decls_end();
if (I == E) OS << " empty";
for (; I != E; ++I)
OS << " " << (void*) *I;
}
void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
DumpExpr(Node);
OS << " " << Node->getDecl()->getDeclKindName()
<< "Decl='" << *Node->getDecl()
<< "' " << (void*)Node->getDecl();
if (Node->isFreeIvar())
OS << " isFreeIvar";
}
void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) {
DumpExpr(Node);
switch (Node->getIdentType()) {
default: llvm_unreachable("unknown case");
case PredefinedExpr::Func: OS << " __func__"; break;
case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
}
}
void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) {
DumpExpr(Node);
OS << " " << Node->getValue();
}
void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) {
DumpExpr(Node);
bool isSigned = Node->getType()->isSignedIntegerType();
OS << " " << Node->getValue().toString(10, isSigned);
}
void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) {
DumpExpr(Node);
OS << " " << Node->getValueAsApproximateDouble();
}
void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
DumpExpr(Str);
// FIXME: this doesn't print wstrings right.
OS << " ";
switch (Str->getKind()) {
case StringLiteral::Ascii: break; // No prefix
case StringLiteral::Wide: OS << 'L'; break;
case StringLiteral::UTF8: OS << "u8"; break;
case StringLiteral::UTF16: OS << 'u'; break;
case StringLiteral::UTF32: OS << 'U'; break;
}
OS << '"';
OS.write_escaped(Str->getString());
OS << '"';
}
void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
DumpExpr(Node);
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
<< " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
}
void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
DumpExpr(Node);
switch(Node->getKind()) {
case UETT_SizeOf:
OS << " sizeof ";
break;
case UETT_AlignOf:
OS << " __alignof ";
break;
case UETT_VecStep:
OS << " vec_step ";
break;
}
if (Node->isArgumentType())
DumpType(Node->getArgumentType());
}
void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
DumpExpr(Node);
OS << " " << (Node->isArrow() ? "->" : ".")
<< *Node->getMemberDecl() << ' '
<< (void*)Node->getMemberDecl();
}
void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
DumpExpr(Node);
OS << " " << Node->getAccessor().getNameStart();
}
void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
DumpExpr(Node);
OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
}
void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
DumpExpr(Node);
OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
<< "' ComputeLHSTy=";
DumpType(Node->getComputationLHSType());
OS << " ComputeResultTy=";
DumpType(Node->getComputationResultType());
}
void StmtDumper::VisitBlockExpr(BlockExpr *Node) {
DumpExpr(Node);
IndentLevel++;
BlockDecl *block = Node->getBlockDecl();
if (block->capturesCXXThis()) {
OS << '\n'; Indent(); OS << "(capture this)";
}
for (BlockDecl::capture_iterator
i = block->capture_begin(), e = block->capture_end(); i != e; ++i) {
OS << '\n';
Indent();
OS << "(capture ";
if (i->isByRef()) OS << "byref ";
if (i->isNested()) OS << "nested ";
if (i->getVariable())
DumpDeclRef(i->getVariable());
if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr());
OS << ")";
}
IndentLevel--;
DumpSubTree(block->getBody());
}
void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
DumpExpr(Node);
if (Expr *Source = Node->getSourceExpr()) {
OS << '\n';
DumpSubTree(Source);
}
}
// GNU extensions.
void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {
DumpExpr(Node);
OS << " " << Node->getLabel()->getName()
<< " " << (void*)Node->getLabel();
}
//===----------------------------------------------------------------------===//
// C++ Expressions
//===----------------------------------------------------------------------===//
void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
DumpExpr(Node);
OS << " " << Node->getCastName()
<< "<" << Node->getTypeAsWritten().getAsString() << ">"
<< " <" << Node->getCastKindName();
DumpBasePath(OS, Node);
OS << ">";
}
void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
DumpExpr(Node);
OS << " " << (Node->getValue() ? "true" : "false");
}
void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) {
DumpExpr(Node);
OS << " this";
}
void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
DumpExpr(Node);
OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
<< " <" << Node->getCastKindName() << ">";
}
void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
DumpExpr(Node);
CXXConstructorDecl *Ctor = Node->getConstructor();
DumpType(Ctor->getType());
if (Node->isElidable())
OS << " elidable";
if (Node->requiresZeroInitialization())
OS << " zeroing";
}
void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
DumpExpr(Node);
OS << " ";
DumpCXXTemporary(Node->getTemporary());
}
void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
DumpExpr(Node);
++IndentLevel;
for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) {
OS << "\n";
Indent();
OS << "(cleanup ";
DumpDeclRef(Node->getObject(i));
OS << ")";
}
--IndentLevel;
}
void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
OS << "(CXXTemporary " << (void *)Temporary << ")";
}
//===----------------------------------------------------------------------===//
// Obj-C Expressions
//===----------------------------------------------------------------------===//
void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
DumpExpr(Node);
OS << " selector=" << Node->getSelector().getAsString();
switch (Node->getReceiverKind()) {
case ObjCMessageExpr::Instance:
break;
case ObjCMessageExpr::Class:
OS << " class=";
DumpType(Node->getClassReceiver());
break;
case ObjCMessageExpr::SuperInstance:
OS << " super (instance)";
break;
case ObjCMessageExpr::SuperClass:
OS << " super (class)";
break;
}
}
void StmtDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) {
DumpStmt(Node);
if (VarDecl *CatchParam = Node->getCatchParamDecl()) {
OS << " catch parm = ";
DumpDeclarator(CatchParam);
} else {
OS << " catch all";
}
}
void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
DumpExpr(Node);
OS << " ";
DumpType(Node->getEncodedType());
}
void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
DumpExpr(Node);
OS << " " << Node->getSelector().getAsString();
}
void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
DumpExpr(Node);
OS << ' ' <<* Node->getProtocol();
}
void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
DumpExpr(Node);
if (Node->isImplicitProperty()) {
OS << " Kind=MethodRef Getter=\"";
if (Node->getImplicitPropertyGetter())
OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
else
OS << "(null)";
OS << "\" Setter=\"";
if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
OS << Setter->getSelector().getAsString();
else
OS << "(null)";
OS << "\"";
} else {
OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
}
if (Node->isSuperReceiver())
OS << " super";
}
void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
DumpExpr(Node);
if (Node->isArraySubscriptRefExpr())
OS << " Kind=ArraySubscript GetterForArray=\"";
else
OS << " Kind=DictionarySubscript GetterForDictionary=\"";
if (Node->getAtIndexMethodDecl())
OS << Node->getAtIndexMethodDecl()->getSelector().getAsString();
else
OS << "(null)";
if (Node->isArraySubscriptRefExpr())
OS << "\" SetterForArray=\"";
else
OS << "\" SetterForDictionary=\"";
if (Node->setAtIndexMethodDecl())
OS << Node->setAtIndexMethodDecl()->getSelector().getAsString();
else
OS << "(null)";
}
void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
DumpExpr(Node);
OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
}
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
/// dump - This does a local dump of the specified AST fragment. It dumps the
/// specified node and a few nodes underneath it, but not the whole subtree.
/// This is useful in a debugger.
void Stmt::dump(SourceManager &SM) const {
dump(llvm::errs(), SM);
}
void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
StmtDumper P(&SM, OS, 4);
P.DumpSubTree(const_cast<Stmt*>(this));
OS << "\n";
}
/// dump - This does a local dump of the specified AST fragment. It dumps the
/// specified node and a few nodes underneath it, but not the whole subtree.
/// This is useful in a debugger.
void Stmt::dump() const {
StmtDumper P(0, llvm::errs(), 4);
P.DumpSubTree(const_cast<Stmt*>(this));
llvm::errs() << "\n";
}
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void Stmt::dumpAll(SourceManager &SM) const {
StmtDumper P(&SM, llvm::errs(), ~0U);
P.DumpSubTree(const_cast<Stmt*>(this));
llvm::errs() << "\n";
}
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void Stmt::dumpAll() const {
StmtDumper P(0, llvm::errs(), ~0U);
P.DumpSubTree(const_cast<Stmt*>(this));
llvm::errs() << "\n";
}