//===--- PrettyStackTrace.cpp - Swift-specific PrettyStackTraceEntries ----===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements several Swift-specific implementations of // PrettyStackTraceEntry. // //===----------------------------------------------------------------------===// #include "swift/AST/AST.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/TypeVisitor.h" #include "swift/Basic/Optional.h" #include "swift/Basic/SourceManager.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/MemoryBuffer.h" using namespace swift; static void printDecomposedLoc(llvm::raw_ostream &out, const DecomposedLoc &loc) { out << loc.Buffer->getBufferIdentifier() << ":" << loc.Line << ':' << loc.Column; } void swift::printSourceLoc(llvm::raw_ostream &OS, SourceLoc Loc, ASTContext &Context) { if (Loc.isInvalid()) { OS << "<>"; return; } return printDecomposedLoc(OS, Context.SourceMgr.decompose(Loc)); } static void printSourceRange(llvm::raw_ostream &OS, SourceRange SR, ASTContext &Context) { if (SR.isInvalid()) { OS << "<>"; return; } DecomposedLoc Start = Context.SourceMgr.decompose(SR.Start); DecomposedLoc End = Context.SourceMgr.decompose(SR.End); // Print the start location as normal. printDecomposedLoc(OS, Start); OS << '-'; // Only print the non-matching information from the second location. if (Start.Buffer != End.Buffer) { printDecomposedLoc(OS, End); return; } if (Start.Line != End.Line) { OS << End.Line << ':'; } OS << End.Column; } void PrettyStackTraceDecl::print(llvm::raw_ostream &out) const { out << "While " << Action << ' '; if (!TheDecl) { out << "NULL declaration!\n"; return; } printDeclDescription(out, TheDecl, TheDecl->getASTContext()); } void swift::printDeclDescription(llvm::raw_ostream &out, Decl *D, ASTContext &Context) { if (ValueDecl *named = dyn_cast(D)) { if (named->getName().get()) out << '\'' << named->getName() << '\''; else out << "'anonname=" << (const void*)named << '\''; } else { out << "declaration"; } out << " at "; printSourceLoc(out, D->getStartLoc(), Context); out << '\n'; } void PrettyStackTraceExpr::print(llvm::raw_ostream &out) const { out << "While " << Action << ' '; if (!TheExpr) { out << "NULL expression!\n"; return; } printExprDescription(out, TheExpr, Context); } void swift::printExprDescription(llvm::raw_ostream &out, Expr *E, ASTContext &Context) { if (isa(E)) { out << "function"; } else { out << "expression"; } out << " at "; printSourceRange(out, E->getSourceRange(), Context); out << '\n'; } void PrettyStackTraceStmt::print(llvm::raw_ostream &out) const { out << "While " << Action << ' '; if (!TheStmt) { out << "NULL statement!\n"; return; } printStmtDescription(out, TheStmt, Context); } void swift::printStmtDescription(llvm::raw_ostream &out, Stmt *S, ASTContext &Context) { out << "statement at "; printSourceRange(out, S->getSourceRange(), Context); out << '\n'; } void PrettyStackTracePattern::print(llvm::raw_ostream &out) const { out << "While " << Action << ' '; if (!ThePattern) { out << "NULL pattern!\n"; return; } printPatternDescription(out, ThePattern, Context); } void swift::printPatternDescription(llvm::raw_ostream &out, Pattern *P, ASTContext &Context) { out << "pattern at "; printSourceRange(out, P->getSourceRange(), Context); out << '\n'; } namespace { /// Map a Type to an interesting declaration whose source range we /// should print. struct InterestingDeclForType : TypeVisitor { Decl *visitType(TypeBase *type) { return nullptr; } Decl *visitUnboundGenericType(UnboundGenericType *type) { return type->getDecl(); } Decl *visitBoundGenericType(BoundGenericType *type) { return type->getDecl(); } Decl *visitNominalType(NominalType *type) { return type->getDecl(); } Decl *visitNameAliasType(NameAliasType *type) { return type->getDecl(); } }; } void PrettyStackTraceType::print(llvm::raw_ostream &out) const { out << "While " << Action << ' '; if (TheType.isNull()) { out << "NULL type!\n"; return; } printTypeDescription(out, TheType, Context); } void swift::printTypeDescription(llvm::raw_ostream &out, Type type, ASTContext &Context) { out << "type '" << type << '\''; if (Decl *decl = InterestingDeclForType().visit(type)) { out << " (declared at "; printSourceRange(out, decl->getSourceRange(), Context); out << ')'; } out << '\n'; } void PrettyStackTraceLocation::print(llvm::raw_ostream &out) const { out << "While " << Action << " starting at "; printSourceLoc(out, Loc, Context); out << '\n'; }