================ @@ -0,0 +1,465 @@ +//===- ExamplePlugin.cpp - Example SSAF plugin ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// A loadable plugin that demonstrates the full SSAF analysis pipeline. +// +//===----------------------------------------------------------------------===// + +#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h" +#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h" +#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h" +#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h" +#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h" +#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h" +#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h" +#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h" +#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Registry.h" +#include <algorithm> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +using namespace clang::ssaf; +using namespace llvm; + +namespace { + +//===----------------------------------------------------------------------===// +// TagsEntitySummary +// +// Per-entity data: a list of string tags. Stored in the LU data section +// under summary_name "TagsEntitySummary". Serialized as: +// { "tags": ["tag1", "tag2", ...] } +//===----------------------------------------------------------------------===// + +struct TagsEntitySummary final : EntitySummary { + static SummaryName summaryName() { return SummaryName("TagsEntitySummary"); } + + SummaryName getSummaryName() const override { + return SummaryName("TagsEntitySummary"); + } + + std::vector<std::string> Tags; +}; + +json::Object serializeTagsEntitySummary(const EntitySummary &ES, + JSONFormat::EntityIdToJSONFn) { + const auto &S = static_cast<const TagsEntitySummary &>(ES); + json::Array TagsArray; + for (const auto &Tag : S.Tags) { + TagsArray.push_back(Tag); + } + return json::Object{{"tags", std::move(TagsArray)}}; +} + +Expected<std::unique_ptr<EntitySummary>> +deserializeTagsEntitySummary(const json::Object &Obj, EntityIdTable &, + JSONFormat::EntityIdFromJSONFn) { + const json::Array *TagsArray = Obj.getArray("tags"); + if (!TagsArray) { + return createStringError(inconvertibleErrorCode(), + "missing or invalid field 'tags'"); + } + + auto S = std::make_unique<TagsEntitySummary>(); + for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) { + auto Str = Val.getAsString(); + if (!Str) { + return createStringError(inconvertibleErrorCode(), + "tags element at index %zu is not a string", + Index); + } + S->Tags.push_back(Str->str()); + } + return std::move(S); +} + +struct TagsEntitySummaryFormatInfo final : JSONFormat::FormatInfo { + TagsEntitySummaryFormatInfo() + : JSONFormat::FormatInfo(SummaryName("TagsEntitySummary"), + serializeTagsEntitySummary, + deserializeTagsEntitySummary) {} +}; + +llvm::Registry<JSONFormat::FormatInfo>::Add<TagsEntitySummaryFormatInfo> + RegisterTagsEntitySummaryForJSON("TagsEntitySummary", + "JSON format info for TagsEntitySummary"); + +//===----------------------------------------------------------------------===// +// PairsEntitySummary +// +// Per-entity data: a list of (EntityId, EntityId) pairs. Stored in the LU +// data section under summary_name "PairsEntitySummary". Serialized as: +// { "pairs": [{"first": {...}, "second": {...}}, ...] } +//===----------------------------------------------------------------------===// + +struct PairsEntitySummary final : EntitySummary { + static SummaryName summaryName() { return SummaryName("PairsEntitySummary"); } + + SummaryName getSummaryName() const override { + return SummaryName("PairsEntitySummary"); + } + + std::vector<std::pair<EntityId, EntityId>> Pairs; +}; + +json::Object serializePairsEntitySummary(const EntitySummary &ES, + JSONFormat::EntityIdToJSONFn ToJSON) { + const auto &S = static_cast<const PairsEntitySummary &>(ES); + json::Array PairsArray; + for (const auto &[First, Second] : S.Pairs) { + PairsArray.push_back(json::Object{ + {"first", ToJSON(First)}, + {"second", ToJSON(Second)}, + }); + } + return json::Object{{"pairs", std::move(PairsArray)}}; +} + +Expected<std::unique_ptr<EntitySummary>> +deserializePairsEntitySummary(const json::Object &Obj, EntityIdTable &, + JSONFormat::EntityIdFromJSONFn FromJSON) { + auto Result = std::make_unique<PairsEntitySummary>(); + const json::Array *PairsArray = Obj.getArray("pairs"); + if (!PairsArray) { + return createStringError(inconvertibleErrorCode(), + "missing or invalid field 'pairs'"); + } + for (const auto &[Index, Value] : llvm::enumerate(*PairsArray)) { + const json::Object *Pair = Value.getAsObject(); + if (!Pair) { + return createStringError( + inconvertibleErrorCode(), + "pairs element at index %zu is not a JSON object", Index); + } + const json::Object *FirstObj = Pair->getObject("first"); + if (!FirstObj) { + return createStringError( + inconvertibleErrorCode(), + "missing or invalid 'first' field at index '%zu'", Index); + } + const json::Object *SecondObj = Pair->getObject("second"); + if (!SecondObj) { + return createStringError( + inconvertibleErrorCode(), + "missing or invalid 'second' field at index '%zu'", Index); + } + auto ExpectedFirst = FromJSON(*FirstObj); + if (!ExpectedFirst) { + return createStringError(inconvertibleErrorCode(), + "invalid 'first' entity id at index '%zu': %s", + Index, + toString(ExpectedFirst.takeError()).c_str()); + } + auto ExpectedSecond = FromJSON(*SecondObj); + if (!ExpectedSecond) { + return createStringError(inconvertibleErrorCode(), + "invalid 'second' entity id at index '%zu': %s", + Index, + toString(ExpectedSecond.takeError()).c_str()); + } + Result->Pairs.emplace_back(*ExpectedFirst, *ExpectedSecond); + } + return std::move(Result); +} + +struct PairsEntitySummaryFormatInfo final : JSONFormat::FormatInfo { + PairsEntitySummaryFormatInfo() + : JSONFormat::FormatInfo(SummaryName("PairsEntitySummary"), + serializePairsEntitySummary, + deserializePairsEntitySummary) {} +}; + +llvm::Registry<JSONFormat::FormatInfo>::Add<PairsEntitySummaryFormatInfo> + RegisterPairsEntitySummaryForJSON( + "PairsEntitySummary", "JSON format info for PairsEntitySummary"); + +//===----------------------------------------------------------------------===// +// TagsAnalysisResult +// +// Sorted, deduplicated list of all tags seen across entities. Serialized as: +// { "tags": ["tag1", "tag2", ...] } +//===----------------------------------------------------------------------===// + +struct TagsAnalysisResult final : AnalysisResult { + static AnalysisName analysisName() { + return AnalysisName("TagsAnalysisResult"); + } + + std::vector<std::string> Tags; +}; + +json::Object serializeTagsAnalysisResult(const TagsAnalysisResult &R, + JSONFormat::EntityIdToJSONFn) { + json::Array TagsArray; + for (const auto &Tag : R.Tags) { + TagsArray.push_back(Tag); + } ---------------- steakhal wrote:
Sniffing reserve and append_range. https://github.com/llvm/llvm-project/pull/187403 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
