static void StreamFunction(llvm::raw_ostream& o, Value* V) { o << "Function @" << V->getPtr() << '\n'; Interpreter* interp = V->getInterpreter(); const Transaction* T = interp->getLastTransaction(); assert(T->getWrapperFD() && "Must have a wrapper."); clang::FunctionDecl* WrapperFD = T->getWrapperFD(); clang::Expr* ExprAttachedTo = utils::Analyze::GetOrCreateLastExpr(WrapperFD, /*foundAtPos*/0, /*omitDS*/false, &interp->getSema()); const clang::DeclRefExpr* DeclRefExp = llvm::dyn_cast_or_null<clang::DeclRefExpr>(ExprAttachedTo); const clang::FunctionDecl* FD = 0; if (DeclRefExp) FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl()); if (FD) { clang::SourceRange SRange = FD->getSourceRange(); const char* cBegin = 0; const char* cEnd = 0; bool Invalid; if (SRange.isValid()) { clang::SourceManager& SM = V->getASTContext().getSourceManager(); clang::SourceLocation LocBegin = SRange.getBegin(); LocBegin = SM.getExpansionRange(LocBegin).first; o << " at " << SM.getFilename(LocBegin); unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid); if (!Invalid) o << ':' << LineNo; o << ":\n"; bool Invalid = false; cBegin = SM.getCharacterData(LocBegin, &Invalid); if (!Invalid) { clang::SourceLocation LocEnd = SRange.getEnd(); LocEnd = SM.getExpansionRange(LocEnd).second; cEnd = SM.getCharacterData(LocEnd, &Invalid); if (Invalid) cBegin = 0; } else { cBegin = 0; } } if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) { o << llvm::StringRef(cBegin, cEnd - cBegin + 1); } else { const clang::FunctionDecl* FDef; if (FD->hasBody(FDef)) FD = FDef; FD->print(o); //const clang::FunctionDecl* FD // = llvm::cast<const clang::FunctionType>(Ty)->getDecl(); } } else { o << ":\n"; // type-based printing: V->getType().print(o, V->getASTContext().getPrintingPolicy()); } // type-based print() never and decl-based print() sometimes does not include // a final newline: o << '\n'; }