Merge branch 'main' into add-activerecord-annotate

This commit is contained in:
thiggy1342
2022-07-15 11:17:48 -04:00
committed by GitHub
23 changed files with 291 additions and 178 deletions

View File

@@ -3,7 +3,9 @@ CodeQL query help for C and C++
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/cpp/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/cpp-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/cpp/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/cpp/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/cpp/ql/examples>`__.
.. include:: toc-cpp.rst

View File

@@ -3,6 +3,8 @@ CodeQL query help for C#
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/csharp/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/csharp-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/csharp/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/csharp/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/csharp/ql/examples>`__.
.. include:: toc-csharp.rst

View File

@@ -3,6 +3,8 @@ CodeQL query help for Go
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/go/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/go-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/go/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/go/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/go/ql/examples>`__.
.. include:: toc-go.rst

View File

@@ -3,6 +3,8 @@ CodeQL query help for Java
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/java/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/java-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/examples>`__.
.. include:: toc-java.rst

View File

@@ -3,6 +3,8 @@ CodeQL query help for JavaScript
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/javascript/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/javascript-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/javascript/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/javascript/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/javascript/ql/examples>`__.
.. include:: toc-javascript.rst

View File

@@ -3,6 +3,8 @@ CodeQL query help for Python
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/python/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/python-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/python/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/python/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/python/ql/examples>`__.
.. include:: toc-python.rst

View File

@@ -3,6 +3,8 @@ CodeQL query help for Ruby
.. include:: ../reusables/query-help-overview.rst
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/ruby/ql/examples>`__.
These queries are published in the CodeQL query pack ``codeql/ruby-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/ruby/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/ruby/ql/src>`__).
For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/codeql-cli/latest/ruby/ql/examples>`__.
.. include:: toc-ruby.rst

View File

@@ -323,6 +323,7 @@ AppliedPropertyWrapperExpr:
_extends: Expr
Argument:
_extends: Locatable
label: string
_children:
expr: Expr

View File

@@ -1,11 +1,7 @@
#include "SwiftExtractor.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <sstream>
#include <memory>
#include <unistd.h>
#include <unordered_set>
#include <queue>
@@ -16,8 +12,9 @@
#include <llvm/Support/Path.h>
#include "swift/extractor/trap/generated/TrapClasses.h"
#include "swift/extractor/trap/TrapOutput.h"
#include "swift/extractor/trap/TrapDomain.h"
#include "swift/extractor/visitors/SwiftVisitor.h"
#include "swift/extractor/infra/TargetFile.h"
using namespace codeql;
@@ -52,7 +49,7 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
}
}
static std::string getTrapFilename(swift::ModuleDecl& module, swift::SourceFile* primaryFile) {
static std::string getFilename(swift::ModuleDecl& module, swift::SourceFile* primaryFile) {
if (primaryFile) {
return primaryFile->getFilename().str();
}
@@ -76,60 +73,45 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
return ret;
}
static void dumpArgs(TargetFile& out, const SwiftExtractorConfiguration& config) {
out << "/* extractor-args:\n";
for (const auto& opt : config.frontendOptions) {
out << " " << std::quoted(opt) << " \\\n";
}
out << "\n*/\n";
out << "/* swift-frontend-args:\n";
for (const auto& opt : config.patchedFrontendOptions) {
out << " " << std::quoted(opt) << " \\\n";
}
out << "\n*/\n";
}
static void extractDeclarations(const SwiftExtractorConfiguration& config,
swift::CompilerInstance& compiler,
swift::ModuleDecl& module,
swift::SourceFile* primaryFile = nullptr) {
auto filename = getFilename(module, primaryFile);
// The extractor can be called several times from different processes with
// the same input file(s)
// We are using PID to avoid concurrent access
// TODO: find a more robust approach to avoid collisions?
auto name = getTrapFilename(module, primaryFile);
llvm::StringRef filename(name);
std::string tempTrapName = filename.str() + '.' + std::to_string(getpid()) + ".trap";
llvm::SmallString<PATH_MAX> tempTrapPath(config.getTempTrapDir());
llvm::sys::path::append(tempTrapPath, tempTrapName);
llvm::StringRef tempTrapParent = llvm::sys::path::parent_path(tempTrapPath);
if (std::error_code ec = llvm::sys::fs::create_directories(tempTrapParent)) {
std::cerr << "Cannot create temp trap directory '" << tempTrapParent.str()
<< "': " << ec.message() << "\n";
// the same input file(s). Using `TargetFile` the first process will win, and the following
// will just skip the work
auto trapTarget = TargetFile::create(filename + ".trap", config.trapDir, config.getTempTrapDir());
if (!trapTarget) {
// another process arrived first, nothing to do for us
return;
}
std::ofstream trapStream(tempTrapPath.str().str());
if (!trapStream) {
std::error_code ec;
ec.assign(errno, std::generic_category());
std::cerr << "Cannot create temp trap file '" << tempTrapPath.str().str()
<< "': " << ec.message() << "\n";
return;
}
trapStream << "/* extractor-args:\n";
for (auto opt : config.frontendOptions) {
trapStream << " " << std::quoted(opt) << " \\\n";
}
trapStream << "\n*/\n";
trapStream << "/* swift-frontend-args:\n";
for (auto opt : config.patchedFrontendOptions) {
trapStream << " " << std::quoted(opt) << " \\\n";
}
trapStream << "\n*/\n";
TrapOutput trap{trapStream};
TrapArena arena{};
dumpArgs(*trapTarget, config);
TrapDomain trap{*trapTarget};
// TODO: move default location emission elsewhere, possibly in a separate global trap file
auto unknownFileLabel = arena.allocateLabel<FileTag>();
// the following cannot conflict with actual files as those have an absolute path starting with /
trap.assignKey(unknownFileLabel, "unknown");
auto unknownFileLabel = trap.createLabel<FileTag>("unknown");
auto unknownLocationLabel = trap.createLabel<LocationTag>("unknown");
trap.emit(FilesTrap{unknownFileLabel});
auto unknownLocationLabel = arena.allocateLabel<LocationTag>();
trap.assignKey(unknownLocationLabel, "unknown");
trap.emit(LocationsTrap{unknownLocationLabel, unknownFileLabel});
SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap, module, primaryFile);
SwiftVisitor visitor(compiler.getSourceMgr(), trap, module, primaryFile);
auto topLevelDecls = getTopLevelDecls(module, primaryFile);
for (auto decl : topLevelDecls) {
visitor.extract(decl);
@@ -142,28 +124,9 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
// fact that the file was extracted
llvm::SmallString<PATH_MAX> name(filename);
llvm::sys::fs::make_absolute(name);
auto fileLabel = arena.allocateLabel<FileTag>();
trap.assignKey(fileLabel, name.str().str());
auto fileLabel = trap.createLabel<FileTag>(name.str().str());
trap.emit(FilesTrap{fileLabel, name.str().str()});
}
// TODO: Pick a better name to avoid collisions
std::string trapName = filename.str() + ".trap";
llvm::SmallString<PATH_MAX> trapPath(config.trapDir);
llvm::sys::path::append(trapPath, trapName);
llvm::StringRef trapParent = llvm::sys::path::parent_path(trapPath);
if (std::error_code ec = llvm::sys::fs::create_directories(trapParent)) {
std::cerr << "Cannot create trap directory '" << trapParent.str() << "': " << ec.message()
<< "\n";
return;
}
// TODO: The last process wins. Should we do better than that?
if (std::error_code ec = llvm::sys::fs::rename(tempTrapPath, trapPath)) {
std::cerr << "Cannot rename temp trap file '" << tempTrapPath.str().str() << "' -> '"
<< trapPath.str().str() << "': " << ec.message() << "\n";
}
}
static std::unordered_set<std::string> collectInputFilenames(swift::CompilerInstance& compiler) {

View File

@@ -2,9 +2,11 @@ load("//swift:rules.bzl", "swift_cc_library")
swift_cc_library(
name = "infra",
srcs = glob(["*.cpp"]),
hdrs = glob(["*.h"]),
visibility = ["//swift:__subpackages__"],
deps = [
"//swift/extractor/trap",
"//swift/tools/prebuilt:swift-llvm-support",
],
)

View File

@@ -4,9 +4,8 @@
#include <swift/Basic/SourceManager.h>
#include <llvm/Support/FileSystem.h>
#include "swift/extractor/trap/TrapArena.h"
#include "swift/extractor/trap/TrapLabelStore.h"
#include "swift/extractor/trap/TrapOutput.h"
#include "swift/extractor/trap/TrapDomain.h"
#include "swift/extractor/infra/SwiftTagTraits.h"
#include "swift/extractor/trap/generated/TrapClasses.h"
@@ -22,12 +21,10 @@ class SwiftDispatcher {
// all references and pointers passed as parameters to this constructor are supposed to outlive
// the SwiftDispatcher
SwiftDispatcher(const swift::SourceManager& sourceManager,
TrapArena& arena,
TrapOutput& trap,
TrapDomain& trap,
swift::ModuleDecl& currentModule,
swift::SourceFile* currentPrimarySourceFile = nullptr)
: sourceManager{sourceManager},
arena{arena},
trap{trap},
currentModule{currentModule},
currentPrimarySourceFile{currentPrimarySourceFile} {}
@@ -77,6 +74,7 @@ class SwiftDispatcher {
}
waitingForNewLabel = e;
visit(e);
// TODO when everything is moved to structured C++ classes, this should be moved to createEntry
if (auto l = store.get(e)) {
if constexpr (!std::is_base_of_v<swift::TypeBase, E>) {
attachLocation(e, *l);
@@ -95,13 +93,17 @@ class SwiftDispatcher {
return fetchLabelFromUnion<AstNodeTag>(node);
}
TrapLabel<ConditionElementTag> fetchLabel(const swift::StmtConditionElement& element) {
return fetchLabel(&element);
}
// Due to the lazy emission approach, we must assign a label to a corresponding AST node before
// it actually gets emitted to handle recursive cases such as recursive calls, or recursive type
// declarations
template <typename E, typename... Args>
TrapLabelOf<E> assignNewLabel(E* e, Args&&... args) {
assert(waitingForNewLabel == Store::Handle{e} && "assignNewLabel called on wrong entity");
auto label = createLabel<TrapTagOf<E>>(std::forward<Args>(args)...);
auto label = trap.createLabel<TrapTagOf<E>>(std::forward<Args>(args)...);
store.insert(e, label);
waitingForNewLabel = std::monostate{};
return label;
@@ -118,18 +120,13 @@ class SwiftDispatcher {
return TrapClassOf<E>{assignNewLabel(&e, std::forward<Args>(args)...)};
}
template <typename Tag>
TrapLabel<Tag> createLabel() {
auto ret = arena.allocateLabel<Tag>();
trap.assignStar(ret);
return ret;
}
template <typename Tag, typename... Args>
TrapLabel<Tag> createLabel(Args&&... args) {
auto ret = arena.allocateLabel<Tag>();
trap.assignKey(ret, std::forward<Args>(args)...);
return ret;
// used to create a new entry for entities that should not be cached
// an example is swift::Argument, that are created on the fly and thus have no stable pointer
template <typename E, typename... Args, std::enable_if_t<!std::is_pointer_v<E>>* = nullptr>
auto createUncachedEntry(const E& e, Args&&... args) {
auto label = trap.createLabel<TrapTagOf<E>>(std::forward<Args>(args)...);
attachLocation(&e, label);
return TrapClassOf<E>{label};
}
template <typename Locatable>
@@ -213,6 +210,7 @@ class SwiftDispatcher {
using Store = TrapLabelStore<swift::Decl,
swift::Stmt,
swift::StmtCondition,
swift::StmtConditionElement,
swift::CaseLabelItem,
swift::Expr,
swift::Pattern,
@@ -227,13 +225,13 @@ class SwiftDispatcher {
return;
}
std::string filepath = getFilepath(start);
auto fileLabel = createLabel<FileTag>(filepath);
auto fileLabel = trap.createLabel<FileTag>(filepath);
// TODO: do not emit duplicate trap entries for Files
trap.emit(FilesTrap{fileLabel, filepath});
auto [startLine, startColumn] = sourceManager.getLineAndColumnInBuffer(start);
auto [endLine, endColumn] = sourceManager.getLineAndColumnInBuffer(end);
auto locLabel = createLabel<LocationTag>('{', fileLabel, "}:", startLine, ':', startColumn, ':',
endLine, ':', endColumn);
auto locLabel = trap.createLabel<LocationTag>('{', fileLabel, "}:", startLine, ':', startColumn,
':', endLine, ':', endColumn);
trap.emit(LocationsTrap{locLabel, fileLabel, startLine, startColumn, endLine, endColumn});
trap.emit(LocatableLocationsTrap{locatableLabel, locLabel});
}
@@ -275,7 +273,8 @@ class SwiftDispatcher {
// which are to be introduced in follow-up PRs
virtual void visit(swift::Decl* decl) = 0;
virtual void visit(swift::Stmt* stmt) = 0;
virtual void visit(swift::StmtCondition* cond) = 0;
virtual void visit(const swift::StmtCondition* cond) = 0;
virtual void visit(const swift::StmtConditionElement* cond) = 0;
virtual void visit(swift::CaseLabelItem* item) = 0;
virtual void visit(swift::Expr* expr) = 0;
virtual void visit(swift::Pattern* pattern) = 0;
@@ -283,8 +282,7 @@ class SwiftDispatcher {
virtual void visit(swift::TypeBase* type) = 0;
const swift::SourceManager& sourceManager;
TrapArena& arena;
TrapOutput& trap;
TrapDomain& trap;
Store store;
Store::Handle waitingForNewLabel{std::monostate{}};
swift::ModuleDecl& currentModule;

View File

@@ -36,12 +36,14 @@ using SILBoxTypeReprTag = SilBoxTypeReprTag;
MAP_TAG(Stmt);
MAP_TAG(StmtCondition);
MAP_TYPE_TO_TAG(StmtConditionElement, ConditionElementTag);
MAP_TAG(CaseLabelItem);
#define ABSTRACT_STMT(CLASS, PARENT) MAP_SUBTAG(CLASS##Stmt, PARENT)
#define STMT(CLASS, PARENT) ABSTRACT_STMT(CLASS, PARENT)
#include <swift/AST/StmtNodes.def>
MAP_TAG(Expr);
MAP_TAG(Argument);
#define ABSTRACT_EXPR(CLASS, PARENT) MAP_SUBTAG(CLASS##Expr, PARENT)
#define EXPR(CLASS, PARENT) ABSTRACT_EXPR(CLASS, PARENT)
#include <swift/AST/ExprNodes.def>

View File

@@ -0,0 +1,85 @@
#include "swift/extractor/infra/TargetFile.h"
#include <iostream>
#include <cstdio>
#include <cerrno>
#include <system_error>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Path.h>
namespace codeql {
namespace {
[[noreturn]] void error(const char* action, const std::string& arg, std::error_code ec) {
std::cerr << "Unable to " << action << ": " << arg << " (" << ec.message() << ")\n";
std::abort();
}
[[noreturn]] void error(const char* action, const std::string& arg) {
error(action, arg, {errno, std::system_category()});
}
void ensureParentDir(const std::string& path) {
auto parent = llvm::sys::path::parent_path(path);
if (auto ec = llvm::sys::fs::create_directories(parent)) {
error("create directory", parent.str(), ec);
}
}
std::string initPath(std::string_view target, std::string_view dir) {
std::string ret{dir};
assert(!target.empty() && "target must be a non-empty path");
if (target[0] != '/') {
ret += '/';
}
ret.append(target);
ensureParentDir(ret);
return ret;
}
} // namespace
TargetFile::TargetFile(std::string_view target,
std::string_view targetDir,
std::string_view workingDir)
: workingPath{initPath(target, workingDir)}, targetPath{initPath(target, targetDir)} {}
bool TargetFile::init() {
errno = 0;
// since C++17 "x" mode opens with O_EXCL (fails if file already exists)
if (auto f = std::fopen(targetPath.c_str(), "wx")) {
std::fclose(f);
out.open(workingPath);
checkOutput("open file for writing");
return true;
}
if (errno != EEXIST) {
error("open file for writing", targetPath);
}
// else we just lost the race
return false;
}
std::optional<TargetFile> TargetFile::create(std::string_view target,
std::string_view targetDir,
std::string_view workingDir) {
TargetFile ret{target, targetDir, workingDir};
if (ret.init()) return ret;
return std::nullopt;
}
void TargetFile::commit() {
if (out.is_open()) {
out.close();
errno = 0;
if (std::rename(workingPath.c_str(), targetPath.c_str()) != 0) {
error("rename file", targetPath);
}
}
}
void TargetFile::checkOutput(const char* action) {
if (!out) {
error(action, workingPath);
}
}
} // namespace codeql

View File

@@ -0,0 +1,46 @@
#pragma once
#include <string>
#include <fstream>
#include <optional>
#include <cerrno>
namespace codeql {
// Only the first process trying to create a `TargetFile` for a given `target` is allowed to do
// so, all others will have `create` return `std::nullopt`.
// The content streamed to the `TargetFile` is written to `workingDir/target`, and is moved onto
// `targetDir/target` on destruction.
class TargetFile {
std::string workingPath;
std::string targetPath;
std::ofstream out;
public:
static std::optional<TargetFile> create(std::string_view target,
std::string_view targetDir,
std::string_view workingDir);
~TargetFile() { commit(); }
TargetFile(TargetFile&& other) = default;
// move assignment deleted as non-trivial and not needed
TargetFile& operator=(TargetFile&& other) = delete;
template <typename T>
TargetFile& operator<<(T&& value) {
errno = 0;
out << value;
checkOutput("write to file");
return *this;
}
private:
TargetFile(std::string_view target, std::string_view targetDir, std::string_view workingDir);
bool init();
void checkOutput(const char* action);
void commit();
};
} // namespace codeql

View File

@@ -1,23 +0,0 @@
#pragma once
#include <iostream>
#include <sstream>
#include <vector>
#include "swift/extractor/trap/TrapLabel.h"
namespace codeql {
// TrapArena has the responsibilities to allocate distinct trap #-labels
// TODO this is now a small functionality that will be moved to code upcoming from other PRs
class TrapArena {
uint64_t id_{0};
public:
template <typename Tag>
TrapLabel<Tag> allocateLabel() {
return TrapLabel<Tag>::unsafeCreateFromExplicitId(id_++);
}
};
} // namespace codeql

View File

@@ -1,19 +1,58 @@
#pragma once
#include <memory>
#include <sstream>
#include "swift/extractor/trap/TrapLabel.h"
#include "swift/extractor/infra/TargetFile.h"
namespace codeql {
// Sink for trap emissions and label assignments. This abstracts away `ofstream` operations
// like `ofstream`, an explicit bool operator is provided, that return false if something
// went wrong
// TODO better error handling
class TrapOutput {
std::ostream& out_;
// Abstracts a given trap output file, with its own universe of trap labels
class TrapDomain {
TargetFile& out_;
public:
explicit TrapOutput(std::ostream& out) : out_{out} {}
explicit TrapDomain(TargetFile& out) : out_{out} {}
template <typename Entry>
void emit(const Entry& e) {
print(e);
}
template <typename... Args>
void debug(const Args&... args) {
print("/* DEBUG:");
print(args...);
print("*/");
}
template <typename Tag>
TrapLabel<Tag> createLabel() {
auto ret = allocateLabel<Tag>();
assignStar(ret);
return ret;
}
template <typename Tag, typename... Args>
TrapLabel<Tag> createLabel(Args&&... args) {
auto ret = allocateLabel<Tag>();
assignKey(ret, std::forward<Args>(args)...);
return ret;
}
private:
uint64_t id_{0};
template <typename Tag>
TrapLabel<Tag> allocateLabel() {
return TrapLabel<Tag>::unsafeCreateFromExplicitId(id_++);
}
template <typename... Args>
void print(const Args&... args) {
(out_ << ... << args) << '\n';
}
template <typename Tag>
void assignStar(TrapLabel<Tag> label) {
@@ -33,23 +72,6 @@ class TrapOutput {
(oss << ... << keyParts);
assignKey(label, oss.str());
}
template <typename Entry>
void emit(const Entry& e) {
print(e);
}
template <typename... Args>
void debug(const Args&... args) {
out_ << "/* DEBUG:\n";
(out_ << ... << args) << "\n*/\n";
}
private:
template <typename... Args>
void print(const Args&... args) {
(out_ << ... << args) << '\n';
}
};
} // namespace codeql

View File

@@ -611,11 +611,11 @@ void ExprVisitor::fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr
}
TrapLabel<ArgumentTag> ExprVisitor::emitArgument(const swift::Argument& arg) {
auto argLabel = dispatcher_.createLabel<ArgumentTag>();
assert(arg.getExpr() && "Argument has getExpr");
dispatcher_.emit(
ArgumentsTrap{argLabel, arg.getLabel().str().str(), dispatcher_.fetchLabel(arg.getExpr())});
return argLabel;
auto entry = dispatcher_.createUncachedEntry(arg);
entry.label = arg.getLabel().str().str();
entry.expr = dispatcher_.fetchLabel(arg.getExpr());
dispatcher_.emit(entry);
return entry.id;
}
void ExprVisitor::emitImplicitConversionExpr(swift::ImplicitConversionExpr* expr,

View File

@@ -7,26 +7,22 @@ void StmtVisitor::visitLabeledStmt(swift::LabeledStmt* stmt) {
emitLabeledStmt(stmt, label);
}
void StmtVisitor::visitStmtCondition(swift::StmtCondition* cond) {
auto label = dispatcher_.assignNewLabel(cond);
dispatcher_.emit(StmtConditionsTrap{label});
unsigned index = 0;
for (const auto& cond : *cond) {
auto condLabel = dispatcher_.createLabel<ConditionElementTag>();
dispatcher_.attachLocation(cond, condLabel);
dispatcher_.emit(ConditionElementsTrap{condLabel});
dispatcher_.emit(StmtConditionElementsTrap{label, index++, condLabel});
if (auto boolean = cond.getBooleanOrNull()) {
auto elementLabel = dispatcher_.fetchLabel(boolean);
dispatcher_.emit(ConditionElementBooleansTrap{condLabel, elementLabel});
} else if (auto pattern = cond.getPatternOrNull()) {
auto patternLabel = dispatcher_.fetchLabel(pattern);
auto initilizerLabel = dispatcher_.fetchLabel(cond.getInitializer());
dispatcher_.emit(ConditionElementPatternsTrap{condLabel, patternLabel});
dispatcher_.emit(ConditionElementInitializersTrap{condLabel, initilizerLabel});
}
/// TODO: Implement availability
codeql::StmtCondition StmtVisitor::translateStmtCondition(const swift::StmtCondition& cond) {
auto entry = dispatcher_.createEntry(cond);
entry.elements = dispatcher_.fetchRepeatedLabels(cond);
return entry;
}
codeql::ConditionElement StmtVisitor::translateStmtConditionElement(
const swift::StmtConditionElement& element) {
auto entry = dispatcher_.createEntry(element);
if (auto boolean = element.getBooleanOrNull()) {
entry.boolean = dispatcher_.fetchLabel(boolean);
} else if (auto pattern = element.getPatternOrNull()) {
entry.pattern = dispatcher_.fetchLabel(pattern);
entry.initializer = dispatcher_.fetchLabel(element.getInitializer());
}
return entry;
}
void StmtVisitor::visitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt) {

View File

@@ -10,7 +10,9 @@ class StmtVisitor : public AstVisitorBase<StmtVisitor> {
using AstVisitorBase<StmtVisitor>::AstVisitorBase;
void visitLabeledStmt(swift::LabeledStmt* stmt);
void visitStmtCondition(swift::StmtCondition* cond);
codeql::StmtCondition translateStmtCondition(const swift::StmtCondition& cond);
codeql::ConditionElement translateStmtConditionElement(
const swift::StmtConditionElement& element);
void visitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt);
void visitCaseLabelItem(swift::CaseLabelItem* labelItem);
void visitBraceStmt(swift::BraceStmt* stmt);

View File

@@ -22,7 +22,12 @@ class SwiftVisitor : private SwiftDispatcher {
private:
void visit(swift::Decl* decl) override { declVisitor.visit(decl); }
void visit(swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
void visit(swift::StmtCondition* cond) override { stmtVisitor.visitStmtCondition(cond); }
void visit(const swift::StmtCondition* cond) override {
emit(stmtVisitor.translateStmtCondition(*cond));
}
void visit(const swift::StmtConditionElement* element) override {
emit(stmtVisitor.translateStmtConditionElement(*element));
}
void visit(swift::CaseLabelItem* item) override { stmtVisitor.visitCaseLabelItem(item); }
void visit(swift::Expr* expr) override { exprVisitor.visit(expr); }
void visit(swift::Pattern* pattern) override { patternVisitor.visit(pattern); }

View File

@@ -1,8 +1,8 @@
// generated by codegen/codegen.py
import codeql.swift.elements.Element
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.Locatable
class ArgumentBase extends @argument, Element {
class ArgumentBase extends @argument, Locatable {
override string getAPrimaryQlClass() { result = "Argument" }
string getLabel() { arguments(this, result, _) }

View File

@@ -13,8 +13,7 @@ sourceLocationPrefix(
// from codegen/schema.yml
@element =
@argument
| @callable
@callable
| @file
| @generic_context
| @iterable_decl_context
@@ -34,7 +33,8 @@ files(
);
@locatable =
@ast_node
@argument
| @ast_node
| @condition_element
;

View File

@@ -1,2 +1,2 @@
| dot_syntax_call.swift:6:1:6:3 | call to foo(_:_:) | 0 | : X.Type |
| dot_syntax_call.swift:7:1:7:3 | call to bar() | 0 | : X.Type |
| dot_syntax_call.swift:6:1:6:3 | call to foo(_:_:) | 0 | dot_syntax_call.swift:6:1:6:1 | : X.Type |
| dot_syntax_call.swift:7:1:7:3 | call to bar() | 0 | dot_syntax_call.swift:7:1:7:1 | : X.Type |