Exemplo n.º 1
0
void DoubleFetchChecker::checkPreStmt(const CallExpr *CE, CheckerContext &Ctx) const{
	ProgramStateRef state = Ctx.getState();
	const FunctionDecl *FDecl = Ctx.getCalleeDecl(CE);
	StringRef funcName = Ctx.getCalleeName(FDecl);
	//std::cout<<"[checkPreStmt<CallExpr>] func name is:"<<funcName.<<std::endl;
	//printf("[checkPreStmt<CallExpr>] func name is:%s\n",funcName);
	//std::cout<<"-------------------->getLocStart: "<<CE->getLocStart().getRawEncoding()<<std::endl;
	//std::cout<<"--------------------->getLocEnd: "<<CE->getLocEnd().getRawEncoding()<<std::endl;
	//std::cout<<"-------------------->getExprLoc: "<<CE->getExprLoc().getRawEncoding()<<std::endl;

	unsigned int spelling = Ctx.getSourceManager().getSpellingLineNumber(CE->getExprLoc());
	unsigned int ex = Ctx.getSourceManager().getExpansionLineNumber(CE->getExprLoc());

}
std::unique_ptr<BugReport>
MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
    const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const {
  const ADFunctionInfo &FI = FunctionsToTrack[AP.second->AllocatorIdx];
  initBugType();
  SmallString<70> sbuf;
  llvm::raw_svector_ostream os(sbuf);
  os << "Allocated data is not released: missing a call to '"
      << FunctionsToTrack[FI.DeallocatorIdx].Name << "'.";

  // Most bug reports are cached at the location where they occurred.
  // With leaks, we want to unique them by the location where they were
  // allocated, and only report a single path.
  PathDiagnosticLocation LocUsedForUniqueing;
  const ExplodedNode *AllocNode = getAllocationNode(N, AP.first, C);
  const Stmt *AllocStmt = nullptr;
  ProgramPoint P = AllocNode->getLocation();
  if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
    AllocStmt = Exit->getCalleeContext()->getCallSite();
  else if (Optional<clang::PostStmt> PS = P.getAs<clang::PostStmt>())
    AllocStmt = PS->getStmt();

  if (AllocStmt)
    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
                                              C.getSourceManager(),
                                              AllocNode->getLocationContext());

  auto Report =
      llvm::make_unique<BugReport>(*BT, os.str(), N, LocUsedForUniqueing,
                                  AllocNode->getLocationContext()->getDecl());

  Report->addVisitor(llvm::make_unique<SecKeychainBugVisitor>(AP.first));
  markInteresting(Report.get(), AP);
  return Report;
}
Exemplo n.º 3
0
void DoubleFetchChecker::checkBind(SVal loc, SVal val,const Stmt *StoreE,CheckerContext &Ctx) const{

	ProgramStateRef state = Ctx.getState();
	std::cout<<"\n";

	unsigned int bloc = Ctx.getSourceManager().getExpansionLineNumber(StoreE->getLocEnd());
	std::cout<<"[checkBind] location: "<<bloc<<std::endl;

	const LocationContext *LC = Ctx.getLocationContext();
	const Decl *D = LC->getAnalysisDeclContext()->getDecl();
	const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
	std::string funcName = FD->getNameAsString();



	std::cout<<"[checkbind()]"<<" funcName is: "<<funcName<<std::endl;
	if(isValTainted(state,val)){
		std::cout<<"[checkbind()] tainted"<<"\tlocation is: "<<toStr(loc)<<"\tbind value is: "<<toStr(val)<<std::endl;
		unsigned int curTime = this->getCurTime(state);
		TaintList *tl = this->getTaintList(state, val);
		if(tl != NULL)
			tl->showTaints("--->");

		/* it is the value in loc that should be reference*/
		SymbolRef sr  = this->getSymbolRef(val);
		if (!sr){
			std::cout<<"[checkbind()]  SymbolRef failed!\n";
			return;
		}

		/*update locationMap.
		 * LocationMap, records when each local var is created.
		 */
		state = state->set<LocalVarAccessRecord>(sr,curTime);
		std::cout<<"--->add loc to LocalVarAccessRecord: SymbolRef is: "<<toStr(sr)<<"\t time is:"<<curTime<<std::endl;

		/*update timer of the checker, only when taint is passed to another expr */
		state = this->increTime(state);
		/*update program state*/
		Ctx.addTransition(state);

	}
	else
		std::cout<<"[checkbind()] untainted"<<"\tlocation is: "<<toStr(loc)<<"\tbind value is: "<<toStr(val)<<std::endl;






}
Exemplo n.º 4
0
void TraversalDumper::checkBranchCondition(const Stmt *Condition,
                                           CheckerContext &C) const {
  // Special-case Objective-C's for-in loop, which uses the entire loop as its
  // condition. We just print the collection expression.
  const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
  if (!Parent) {
    const ParentMap &Parents = C.getLocationContext()->getParentMap();
    Parent = Parents.getParent(Condition);
  }

  // It is mildly evil to print directly to llvm::outs() rather than emitting
  // warnings, but this ensures things do not get filtered out by the rest of
  // the static analyzer machinery.
  SourceLocation Loc = Parent->getLocStart();
  llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
               << Parent->getStmtClassName() << "\n";
}
void RefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
  const SourceManager& SMgr = Ctx.getSourceManager();

  if (!sym->getOriginRegion())
    return;

  auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
  if (Region) {
    const Decl *PDecl = Region->getDecl();
    if (PDecl && isa<ParmVarDecl>(PDecl)) {
      PathDiagnosticLocation ParamLocation =
          PathDiagnosticLocation::create(PDecl, SMgr);
      Location = ParamLocation;
      UniqueingLocation = ParamLocation;
      UniqueingDecl = Ctx.getLocationContext()->getDecl();
    }
  }
}
void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx,
                                          SymbolRef sym) {
  // Most bug reports are cached at the location where they occurred.
  // With leaks, we want to unique them by the location where they were
  // allocated, and only report a single path.  To do this, we need to find
  // the allocation site of a piece of tracked memory, which we do via a
  // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
  // Note that this is *not* the trimmed graph; we are guaranteed, however,
  // that all ancestor nodes that represent the allocation site have the
  // same SourceLocation.
  const ExplodedNode *AllocNode = nullptr;

  const SourceManager& SMgr = Ctx.getSourceManager();

  AllocationInfo AllocI =
      GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);

  AllocNode = AllocI.N;
  AllocBinding = AllocI.R;
  markInteresting(AllocI.InterestingMethodContext);

  // Get the SourceLocation for the allocation site.
  // FIXME: This will crash the analyzer if an allocation comes from an
  // implicit call (ex: a destructor call).
  // (Currently there are no such allocations in Cocoa, though.)
  AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);

  if (!AllocStmt) {
    AllocBinding = nullptr;
    return;
  }

  PathDiagnosticLocation AllocLocation =
    PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
                                        AllocNode->getLocationContext());
  Location = AllocLocation;

  // Set uniqieing info, which will be used for unique the bug reports. The
  // leaks should be uniqued on the allocation site.
  UniqueingLocation = AllocLocation;
  UniqueingDecl = AllocNode->getLocationContext()->getDecl();
}
Exemplo n.º 7
0
/// Suppress the nullability warnings for some functions.
void NullabilityChecker::checkPostCall(const CallEvent &Call,
                                       CheckerContext &C) const {
  auto Decl = Call.getDecl();
  if (!Decl)
    return;
  // ObjC Messages handles in a different callback.
  if (Call.getKind() == CE_ObjCMessage)
    return;
  const FunctionType *FuncType = Decl->getFunctionType();
  if (!FuncType)
    return;
  QualType ReturnType = FuncType->getReturnType();
  if (!ReturnType->isAnyPointerType())
    return;
  ProgramStateRef State = C.getState();
  if (State->get<PreconditionViolated>())
    return;

  const MemRegion *Region = getTrackRegion(Call.getReturnValue());
  if (!Region)
    return;

  // CG headers are misannotated. Do not warn for symbols that are the results
  // of CG calls.
  const SourceManager &SM = C.getSourceManager();
  StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
  if (llvm::sys::path::filename(FilePath).startswith("CG")) {
    State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
    C.addTransition(State);
    return;
  }

  const NullabilityState *TrackedNullability =
      State->get<NullabilityMap>(Region);

  if (!TrackedNullability &&
      getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
    State = State->set<NullabilityMap>(Region, Nullability::Nullable);
    C.addTransition(State);
  }
}
void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
                                          const Expr *RetE) const {
  ExplodedNode *N = C.generateSink();

  if (!N)
    return;

  if (!BT_returnstack)
   BT_returnstack.reset(
                 new BuiltinBug("Return of address to stack-allocated memory"));

  // Generate a report for this bug.
  SmallString<512> buf;
  llvm::raw_svector_ostream os(buf);
  SourceRange range = GenName(os, R, C.getSourceManager());
  os << " returned to caller";
  BugReport *report = new BugReport(*BT_returnstack, os.str(), N);
  report->addRange(RetE->getSourceRange());
  if (range.isValid())
    report->addRange(range);

  C.EmitReport(report);
}
void StackAddrEscapeChecker::checkEndPath(CheckerContext &Ctx) const {
  ProgramStateRef state = Ctx.getState();

  // Iterate over all bindings to global variables and see if it contains
  // a memory region in the stack space.
  class CallBack : public StoreManager::BindingsHandler {
  private:
    CheckerContext &Ctx;
    const StackFrameContext *CurSFC;
  public:
    SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V;

    CallBack(CheckerContext &CC) :
      Ctx(CC),
      CurSFC(CC.getLocationContext()->getCurrentStackFrame())
    {}
    
    bool HandleBinding(StoreManager &SMgr, Store store,
                       const MemRegion *region, SVal val) {
      
      if (!isa<GlobalsSpaceRegion>(region->getMemorySpace()))
        return true;
      
      const MemRegion *vR = val.getAsRegion();
      if (!vR)
        return true;
        
      // Under automated retain release, it is okay to assign a block
      // directly to a global variable.
      if (Ctx.getASTContext().getLangOpts().ObjCAutoRefCount &&
          isa<BlockDataRegion>(vR))
        return true;

      if (const StackSpaceRegion *SSR = 
          dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) {
        // If the global variable holds a location in the current stack frame,
        // record the binding to emit a warning.
        if (SSR->getStackFrame() == CurSFC)
          V.push_back(std::make_pair(region, vR));
      }
      
      return true;
    }
  };
    
  CallBack cb(Ctx);
  state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);

  if (cb.V.empty())
    return;

  // Generate an error node.
  ExplodedNode *N = Ctx.addTransition(state);
  if (!N)
    return;

  if (!BT_stackleak)
    BT_stackleak.reset(
      new BuiltinBug("Stack address stored into global variable",
                     "Stack address was saved into a global variable. "
                     "This is dangerous because the address will become "
                     "invalid after returning from the function"));
  
  for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
    // Generate a report for this bug.
    SmallString<512> buf;
    llvm::raw_svector_ostream os(buf);
    SourceRange range = GenName(os, cb.V[i].second,
                                Ctx.getSourceManager());
    os << " is still referred to by the global variable '";
    const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
    os << *VR->getDecl()
       << "' upon returning to the caller.  This will be a dangling reference";
    BugReport *report = new BugReport(*BT_stackleak, os.str(), N);
    if (range.isValid())
      report->addRange(range);

    Ctx.EmitReport(report);
  }
}
void DoubleFetchChecker::checkPreCall(const CallEvent &Call,CheckerContext &Ctx) const {
	const IdentifierInfo *ID = Call.getCalleeIdentifier();
	ProgramStateRef state = Ctx.getState();
	if (ID == NULL) {
		return;
	}
	std::cout<<"[checkPreCall]-----call function:"<<ID->getName().str()<<std::endl;


	if(ID->getName() == "kernel_func") {
		ProgramStateRef state = Ctx.getState();
		SVal arg = Call.getArgSVal(0);
		const MemRegion* mr = arg.getAsRegion();
		/*
		state = state->add<TaintRegionMap>(mr);
		Ctx.addTransition(state);

		SVal val = state->getSVal(mr);
		ProgramStateRef newstate = addTaintToSymExpr(state, val);
		if(newstate){
			Ctx.addTransition(newstate);
			std::cout<<"[checkPreCall] arg add taint finish: "<<toStr(arg)<<std::endl;
		}
		else
			std::cout<<"[checkPreCall] arg add taint failed: "<<toStr(arg)<<std::endl;
*/
	}


	if (ID->getName() == "__builtin___memcpy_chk") {
		SVal Arg0 = Call.getArgSVal(0);
		SVal Arg1 = Call.getArgSVal(1);
		SVal Arg2 = Call.getArgSVal(2);

		const Expr * erg0 = Call.getArgExpr(0);

		const Expr * erg1 = Call.getArgExpr(1);

		const Expr * erg2 = Call.getArgExpr(2);

		if(this->isTaintedByTime(state,Arg0)){
			std::cout<<"[checkPreCall]"<<"\tArg0, tainted, \t "<<std::endl;
			showTaintByTime(state, Arg0);

		}
		else
			std::cout<<"[checkPreCall]"<<"\tArg0, not tainted, \t "<<std::endl;

		if(this->isTaintedByTime(state,Arg1)){
			std::cout<<"[checkPreCall]"<<"\tArg1, tainted, \t "<<std::endl;
			showTaintByTime(state, Arg1);
		}
		else
			std::cout<<"[checkPreCall]"<<"\tArg1, not tainted, \t "<<std::endl;

		if(this->isTaintedByTime(state,Arg2)){
			std::cout<<"[checkPreCall]"<<"\tArg2, tainted, \t "<<std::endl;
			showTaintByTime(state, Arg2);
		}
		else
			std::cout<<"[checkPreCall]"<<"\tArg2, not tainted, \t "<<std::endl;

		if(diffTaintInBranch(state,Arg0,erg0,Ctx.getSourceManager())){
			llvm::errs() << "### Found DF1!!#####\n";
			this->reportDoubleFetch(Ctx, Call);
		}
		if(diffTaintInBranch(state,Arg1,erg1,Ctx.getSourceManager())){
			llvm::errs() << "### Found DF2!!#####\n";
			this->reportDoubleFetch(Ctx, Call);
		}
		if(diffTaintInBranch(state,Arg2,erg2, Ctx.getSourceManager())){
			llvm::errs() << "### Found DF3!!#####\n";
			this->reportDoubleFetch(Ctx, Call);

		}
	}

}
Exemplo n.º 11
0
void DoubleFetchChecker::checkBranchCondition(const Stmt *Condition,
	CheckerContext &Ctx) const {

	std::cout<<"\n";
	unsigned int bloc = Ctx.getSourceManager().getExpansionLineNumber(Condition->getLocEnd());
	std::cout<<"[checkBranch] location: "<<bloc<<std::endl;
	ProgramStateRef state = Ctx.getState();

	SVal Val;
	const Expr *exp =  dyn_cast<Expr>(Condition);
	//if is binary branchCondition
	if (const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) {
	    if (B->isComparisonOp()) {
	    	Expr * rp = B->getRHS();
	    	Expr * lp = B->getLHS();

	    	SVal rsval = state->getSVal(rp, Ctx.getLocationContext());
	    	SVal lsval = state->getSVal(lp, Ctx.getLocationContext());

	    	std::cout<<"[checkBranch]--rvalue : "<<toStr(rsval)<<std::endl;
	    	std::cout<<"[checkBranch]--lvalue : "<<toStr(lsval)<<std::endl;

	    	//std::cout<<"[checkBranch]--rvalue expr: \n"<<toStr(rp);
	    	//std::cout<<"[checkBranch]--lvalue expr: \n"<<toStr(lp);

	    	/*use isValTainted instead of isTaintedByTime(),
	    	 * because we need to pass all the taints to the branch,
	    	 * in the form of taintList
	    	 */
	    	std::cout<<"[checkBranch]--rvalue in binary cond\n";
	    	if(this->isTaintedByTime(state,rsval)){
	    		std::cout<<"[checkBranch]"<<"\ttainted, binary rsval is:  "<<toStr(rsval)<<std::endl;
	    		showValTaints(state, rsval, "--->rsval");
	    		state = this->passTaintsToBranch(state, rsval, exp);
	    		Ctx.addTransition(state);
	    	}
	    	 else
	    		std::cout<<"[checkBranch] not tainted"<<"\tbinary rsval is: "<<toStr(rsval)<<std::endl;

	    	std::cout<<"[checkBranch]--lvalue in binary cond\n";
	    	if(this->isTaintedByTime(state,lsval)){
				std::cout<<"[checkBranch]"<<"\ttainted, binary lsval is:  "<<toStr(lsval)<<std::endl;
				showValTaints(state, lsval, "--->lsval");
				state = this->passTaintsToBranch(state, lsval, exp);
				Ctx.addTransition(state);
			}
			 else
				std::cout<<"[checkBranch] not tainted"<<"\tbinary lsval is: "<<toStr(lsval)<<std::endl;

	    }
	}
	//if is unary branchCondition
	else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(Condition)){
		Expr* sp = U->getSubExpr();
		SVal ssval = state->getSVal(sp, Ctx.getLocationContext());

		std::cout<<"[checkBranch]-- in unary cond\n";
		if(this->isTaintedByTime(state,ssval)){
			std::cout<<"[checkBranch]"<<"\ttainted, unary ssval is: ";
			showValTaints(state, ssval, "--->ssval");
			state = this->passTaintsToBranch(state, ssval, exp);
			Ctx.addTransition(state);
		}
		 else
			std::cout<<"[checkBranch] not tainted"<<"\tunary ssval is: "<<toStr(ssval)<<std::endl;

	}
	else{
		std::cout<<"[checkBranch]-- get branch failed\n";
	}
	// two branches
	//ProgramStateRef trueState, falseState;
	//std::tie(trueState, falseState) = state->assume(dv);


}
Exemplo n.º 12
0
void DoubleFetchChecker::checkLocation( SVal loc, bool isLoad, const Stmt* LoadS,
	CheckerContext &Ctx) const{

	std::cout<<"\n";

	const LocationContext *LC = Ctx.getLocationContext();
	const Decl *D = LC->getAnalysisDeclContext()->getDecl();
	const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
	std::string funcName = FD->getNameAsString();

	unsigned int bloc = Ctx.getSourceManager().getExpansionLineNumber(LoadS->getLocEnd());
	std::cout<<"[checkLocation] location: "<<bloc<<std::endl;

	if(funcName == "copy_from_user" || funcName == "get_user")
		return;


	ProgramStateRef state = Ctx.getState();

	const MemRegion *mrptr = loc.getAsRegion();
	if (!mrptr){
		std::cout<<"[checkLocation] get MemRegion failed!\n";
		return;
	}

	std::string locStr = mrptr->getString();
	SVal val= state->getSVal(mrptr);


	unsigned int curTime = this->getCurTime(state);
	bool isTainted;


	std::cout<<"[checkLocation()]"<<" funcName is: "<<funcName<<std::endl;
	std::cout<<"[checkLocation()]"<<"\tlocation is: "<<toStr(loc)<<"\taccess value is: "<<toStr(val)<<"\t time is:"<<curTime<<std::endl;



	if (isLoad){
		/* pass loc to this func, then convert as loc->memregion->val*/
		if(this->isTaintedByTime(state, val)){
			std::cout<<"[checkLocation()] val tainted"<<std::endl;
			isTainted = true;
		}
		else{
			std::cout<<"[checkLocation()] val untainted, return"<<std::endl;
			isTainted = false;
			return;
		}
		/* pass val to this func, no convertion from loc to val*/
		this->showValTaints(state, val, "------>all taints");

	}
	else{
		std::cout<<"[checkLocation()]"<<" write neglect...return\n";
		return;
	}


	this->showLocationMap(state, "--->");

	if(isTainted ){
		/*if(AL.contains(locStr,funcName)){
			std::cout<<"[checkLocation()] is accessing base region"<<std::endl;

		}else{
			std::cout<<"[checkLocation()] is dereference"<<std::endl;
		}*/

		if(diffTaintInBranch(state,val,LoadS,Ctx.getSourceManager())){
			//unsigned int loc = Ctx.getSourceManager().getExpansionLineNumber(LoadS->getLocStart());
			//std::cout<<"------> stmtloc is: "<<loc<<std::endl;
			std::cout << "### Found DF1!!#####\n";
			//ExplodedNode *Node = Ctx.addTransition(state);
			this->reportDoubleFetch(Ctx, state);
		}



	}

}
Exemplo n.º 13
0
void UninitializedObjectChecker::checkEndFunction(
    const ReturnStmt *RS, CheckerContext &Context) const {

  const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
      Context.getLocationContext()->getDecl());
  if (!CtorDecl)
    return;

  if (!CtorDecl->isUserProvided())
    return;

  if (CtorDecl->getParent()->isUnion())
    return;

  // This avoids essentially the same error being reported multiple times.
  if (willObjectBeAnalyzedLater(CtorDecl, Context))
    return;

  Optional<nonloc::LazyCompoundVal> Object = getObjectVal(CtorDecl, Context);
  if (!Object)
    return;

  FindUninitializedFields F(Context.getState(), Object->getRegion(),
                            CheckPointeeInitialization);

  const UninitFieldMap &UninitFields = F.getUninitFields();

  if (UninitFields.empty())
    return;

  // In non-pedantic mode, if Object's region doesn't contain a single
  // initialized field, we'll assume that Object was intentionally left
  // uninitialized.
  if (!IsPedantic && !F.isAnyFieldInitialized())
    return;

  // There are uninitialized fields in the record.

  ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState());
  if (!Node)
    return;

  PathDiagnosticLocation LocUsedForUniqueing;
  const Stmt *CallSite = Context.getStackFrame()->getCallSite();
  if (CallSite)
    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
        CallSite, Context.getSourceManager(), Node->getLocationContext());

  // For Plist consumers that don't support notes just yet, we'll convert notes
  // to warnings.
  if (ShouldConvertNotesToWarnings) {
    for (const auto &Pair : UninitFields) {

      auto Report = llvm::make_unique<BugReport>(
          *BT_uninitField, Pair.second, Node, LocUsedForUniqueing,
          Node->getLocationContext()->getDecl());
      Context.emitReport(std::move(Report));
    }
    return;
  }

  SmallString<100> WarningBuf;
  llvm::raw_svector_ostream WarningOS(WarningBuf);
  WarningOS << UninitFields.size() << " uninitialized field"
            << (UninitFields.size() == 1 ? "" : "s")
            << " at the end of the constructor call";

  auto Report = llvm::make_unique<BugReport>(
      *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
      Node->getLocationContext()->getDecl());

  for (const auto &Pair : UninitFields) {
    Report->addNote(Pair.second,
                    PathDiagnosticLocation::create(Pair.first->getDecl(),
                                                   Context.getSourceManager()));
  }
  Context.emitReport(std::move(Report));
}