//===--- InstrumenterSupport.h - Instrumenter Support -----------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements the supporting functions for writing instrumenters of // the Swift AST. // //===----------------------------------------------------------------------===// #include "TypeChecker.h" #include "swift/AST/ASTWalker.h" namespace swift { namespace instrumenter_support { template class Added { private: E Contents; public: Added() {} Added(E NewContents) : Contents(NewContents) {} Added(const Added &rhs) : Contents(rhs.Contents) {} const Added &operator=(const Added &rhs) { Contents = rhs.Contents; return *this; } E &operator*() { return Contents; } E &operator->() { return Contents; } }; class InstrumenterBase { protected: ASTContext &Context; DeclContext *TypeCheckDC; std::optional ModuleIdentifier; std::optional FileIdentifier; InstrumenterBase(ASTContext &C, DeclContext *DC); virtual ~InstrumenterBase() = default; virtual void anchor(); virtual BraceStmt *transformBraceStmt(BraceStmt *BS, const ParameterList *PL = nullptr, bool TopLevel = false) = 0; /// Create an expression which retrieves a valid ModuleIdentifier or /// FileIdentifier, if available. Expr *buildIDArgumentExpr(std::optional name, SourceRange SR); class ClosureFinder : public ASTWalker { private: InstrumenterBase &I; public: ClosureFinder(InstrumenterBase &Inst) : I(Inst) {} /// Walk only the expansion of the macro. MacroWalking getMacroWalkingBehavior() const override { return MacroWalking::Expansion; } PreWalkResult walkToStmtPre(Stmt *S) override { if (isa(S)) { return Action::SkipNode(S); // don't walk into brace statements; we // need to respect nesting! } else { return Action::Continue(S); } } PreWalkResult walkToExprPre(Expr *E) override { if (auto *CE = dyn_cast(E)) { BraceStmt *B = CE->getBody(); if (B) { const ParameterList *PL = CE->getParameters(); BraceStmt *NB = I.transformBraceStmt(B, PL); CE->setBody(NB); // just with the entry and exit logging this is going to // be more than a single expression! } } return Action::Continue(E); } }; ClosureFinder CF; template bool doTypeCheck(ASTContext &Ctx, DeclContext *DC, Added &parsedExpr) { Expr *E = *parsedExpr; bool result = doTypeCheckImpl(Ctx, DC, E); parsedExpr = Added(dyn_cast(E)); return result; } // Type-check parsedExpr. Note that parsedExpr could end up being changed to // a different kind of expr by the type checker. bool doTypeCheckExpr(ASTContext &Ctx, DeclContext *DC, Expr *&parsedExpr) { return doTypeCheckImpl(Ctx, DC, parsedExpr); } private: bool doTypeCheckImpl(ASTContext &Ctx, DeclContext *DC, Expr * &parsedExpr); }; } }