mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
LLVM has removed llvm::Optional, move over to std::optional. Also clang-format to fix up all the renamed #includes.
145 lines
4.5 KiB
C++
145 lines
4.5 KiB
C++
//===--- InstrumenterSupport.cpp - Instrumenter Support -------------------===//
|
|
//
|
|
// 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 "InstrumenterSupport.h"
|
|
#include "swift/AST/DiagnosticSuppression.h"
|
|
#include "swift/AST/SourceFile.h"
|
|
#include "swift/Demangling/Punycode.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace swift;
|
|
using namespace swift::instrumenter_support;
|
|
|
|
namespace {
|
|
|
|
class ErrorGatherer : public DiagnosticConsumer {
|
|
private:
|
|
bool error = false;
|
|
DiagnosticEngine &diags;
|
|
|
|
public:
|
|
ErrorGatherer(DiagnosticEngine &diags) : diags(diags) {
|
|
diags.addConsumer(*this);
|
|
}
|
|
~ErrorGatherer() override { diags.takeConsumers(); }
|
|
void handleDiagnostic(SourceManager &SM,
|
|
const DiagnosticInfo &Info) override {
|
|
if (Info.Kind == swift::DiagnosticKind::Error) {
|
|
error = true;
|
|
}
|
|
DiagnosticEngine::formatDiagnosticText(llvm::errs(), Info.FormatString,
|
|
Info.FormatArgs);
|
|
llvm::errs() << "\n";
|
|
}
|
|
bool hadError() { return error; }
|
|
};
|
|
|
|
|
|
class ErrorFinder : public ASTWalker {
|
|
bool error = false;
|
|
|
|
public:
|
|
ErrorFinder() {}
|
|
|
|
MacroWalking getMacroWalkingBehavior() const override {
|
|
return MacroWalking::Expansion;
|
|
}
|
|
|
|
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
|
|
if (isa<ErrorExpr>(E) || !E->getType() || E->getType()->hasError())
|
|
error = true;
|
|
|
|
return Action::StopIf(error, E);
|
|
}
|
|
PreWalkAction walkToDeclPre(Decl *D) override {
|
|
if (auto *VD = dyn_cast<ValueDecl>(D)) {
|
|
if (!VD->hasInterfaceType() || VD->getInterfaceType()->hasError())
|
|
error = true;
|
|
}
|
|
return Action::StopIf(error);
|
|
}
|
|
bool hadError() { return error; }
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
InstrumenterBase::InstrumenterBase(ASTContext &C, DeclContext *DC)
|
|
: Context(C), TypeCheckDC(DC), CF(*this) {
|
|
// Prefixes for module and file vars
|
|
const std::string builtinPrefix = "__builtin";
|
|
const std::string modulePrefix = "_pg_module_";
|
|
const std::string filePrefix = "_pg_file_";
|
|
|
|
// Setup Module identifier
|
|
std::string moduleName =
|
|
std::string(TypeCheckDC->getParentModule()->getName());
|
|
Identifier moduleIdentifier =
|
|
Context.getIdentifier(builtinPrefix + modulePrefix + moduleName);
|
|
|
|
SmallVector<ValueDecl *, 1> results;
|
|
TypeCheckDC->getParentModule()->lookupValue(
|
|
moduleIdentifier, NLKind::UnqualifiedLookup, results);
|
|
|
|
if (results.size() == 1)
|
|
ModuleIdentifier = results.front()->createNameRef();
|
|
|
|
// Setup File identifier
|
|
StringRef filePath = TypeCheckDC->getParentSourceFile()->getFilename();
|
|
StringRef fileName = llvm::sys::path::stem(filePath);
|
|
|
|
std::string filePunycodeName;
|
|
Punycode::encodePunycodeUTF8(fileName, filePunycodeName, true);
|
|
Identifier fileIdentifier =
|
|
Context.getIdentifier(builtinPrefix + modulePrefix + moduleName +
|
|
filePrefix + filePunycodeName);
|
|
|
|
results.clear();
|
|
TypeCheckDC->getParentModule()->lookupValue(
|
|
fileIdentifier, NLKind::UnqualifiedLookup, results);
|
|
|
|
if (results.size() == 1)
|
|
FileIdentifier = results.front()->createNameRef();
|
|
}
|
|
|
|
void InstrumenterBase::anchor() {}
|
|
|
|
bool InstrumenterBase::doTypeCheckImpl(ASTContext &Ctx, DeclContext *DC,
|
|
Expr * &parsedExpr) {
|
|
DiagnosticSuppression suppression(Ctx.Diags);
|
|
ErrorGatherer errorGatherer(Ctx.Diags);
|
|
|
|
TypeChecker::typeCheckExpression(parsedExpr, DC, /*contextualInfo=*/{});
|
|
|
|
if (parsedExpr) {
|
|
ErrorFinder errorFinder;
|
|
parsedExpr->walk(errorFinder);
|
|
if (!errorFinder.hadError() && !errorGatherer.hadError()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Expr *InstrumenterBase::buildIDArgumentExpr(std::optional<DeclNameRef> name,
|
|
SourceRange SR) {
|
|
if (!name)
|
|
return IntegerLiteralExpr::createFromUnsigned(Context, 0, SR.End);
|
|
|
|
return new (Context) UnresolvedDeclRefExpr(*name, DeclRefKind::Ordinary,
|
|
DeclNameLoc(SR.End));
|
|
}
|