[clang] Reapply "[clang][ssaf] Add UnsafeBufferUsage summary extractor for functions (#182941)" (PR #186899)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 16 15:09:56 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Ziqing Luo (ziqingluo-90)
<details>
<summary>Changes</summary>
This reverts commit 53739c75a8720aaef8032628267ed4fd050af038.
Reapply after module dependency issues are resolved.
(rdar://169191570)
---
Patch is 36.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/186899.diff
8 Files Affected:
- (renamed) clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h (+20-36)
- (added) clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h (+40)
- (removed) clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h (-32)
- (added) clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt (+15)
- (added) clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp (+281)
- (modified) clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt (+2)
- (modified) clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp (+384-39)
- (modified) clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt (+1)
``````````diff
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
similarity index 62%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
index 5b58ed0684333..5f418000723b4 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
@@ -6,13 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "llvm/ADT/iterator_range.h"
#include <set>
namespace clang::ssaf {
@@ -26,23 +25,19 @@ namespace clang::ssaf {
/// *' of 'p'.
///
/// An EntityPointerLevel can be identified by an EntityId and an unsigned
-/// integer indicating the pointer level: '(EntityId, PointerLevel)'. An
-/// EntityPointerLevel 'P' is valid iff
-/// - 'P.EntityId' has a pointer type with at least 'P.PointerLevel' levels
-/// (This implies 'P.PointerLevel > 0');
-/// - 'P.EntityId' identifies an lvalue object and 'P.PointerLevel == 0'.
-/// The latter case represents address-of expressions.
+/// integer indicating the pointer level: '(EntityId, PointerLevel)'.
+/// An EntityPointerLevel 'P' is valid iff 'P.EntityId' has a pointer type with
+/// at least 'P.PointerLevel' levels (This implies 'P.PointerLevel > 0').
///
/// For the same example 'int *p[10];', the EntityPointerLevels below are valid:
-/// '(p, 1)' is associated with 'int *[10]' of 'p';
-/// '(p, 2)' is associated with 'int *' of 'p';
-/// '(p, 0)' represents '&p'.
+/// - '(p, 2)' is associated with the 'int *' part of the declared type of 'p';
+/// - '(p, 1)' is associated with the 'int *[10]' part of the declared type of
+/// 'p'.
class EntityPointerLevel {
EntityId Entity;
unsigned PointerLevel;
- friend class UnsafeBufferUsageTUSummaryBuilder;
- friend class UnsafeBufferUsageEntitySummary;
+ friend class UnsafeBufferUsageTUSummaryExtractor;
EntityPointerLevel(EntityId Entity, unsigned PointerLevel)
: Entity(Entity), PointerLevel(PointerLevel) {}
@@ -52,7 +47,8 @@ class EntityPointerLevel {
unsigned getPointerLevel() const { return PointerLevel; }
bool operator==(const EntityPointerLevel &Other) const {
- return Entity == Other.Entity && PointerLevel == Other.PointerLevel;
+ return std::tie(Entity, PointerLevel) ==
+ std::tie(Other.Entity, Other.PointerLevel);
}
bool operator!=(const EntityPointerLevel &Other) const {
@@ -64,7 +60,8 @@ class EntityPointerLevel {
std::tie(Other.Entity, Other.PointerLevel);
}
- // Comparator supporting partial comparison against EntityId:
+ /// Compares `EntityPointerLevel`s; additionally, partially compares
+ /// `EntityPointerLevel` with `EntityId`.
struct Comparator {
using is_transparent = void;
bool operator()(const EntityPointerLevel &L,
@@ -88,33 +85,20 @@ using EntityPointerLevelSet =
class UnsafeBufferUsageEntitySummary final : public EntitySummary {
const EntityPointerLevelSet UnsafeBuffers;
- friend class UnsafeBufferUsageTUSummaryBuilder;
+ friend class UnsafeBufferUsageTUSummaryExtractor;
- UnsafeBufferUsageEntitySummary(EntityPointerLevelSet &&UnsafeBuffers)
+ UnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers)
: EntitySummary(), UnsafeBuffers(std::move(UnsafeBuffers)) {}
public:
- using const_iterator = EntityPointerLevelSet::const_iterator;
-
- const_iterator begin() const { return UnsafeBuffers.begin(); }
- const_iterator end() const { return UnsafeBuffers.end(); }
-
- const_iterator find(const EntityPointerLevel &V) const {
- return UnsafeBuffers.find(V);
- }
-
- llvm::iterator_range<const_iterator> getSubsetOf(EntityId Entity) const {
- return llvm::make_range(UnsafeBuffers.equal_range(Entity));
- }
-
- /// \return the size of the set of EntityLevelPointers, which represents the
- /// set of unsafe buffers
- size_t getNumUnsafeBuffers() { return UnsafeBuffers.size(); }
-
SummaryName getSummaryName() const override {
return SummaryName{"UnsafeBufferUsage"};
};
+
+ bool operator==(const EntityPointerLevelSet &Other) const {
+ return UnsafeBuffers == Other;
+ }
};
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h
new file mode 100644
index 0000000000000..765b2c37562ce
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h
@@ -0,0 +1,40 @@
+//===- UnsafeBufferUsageExtractor.h -----------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
+
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+
+namespace clang::ssaf {
+class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
+public:
+ UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
+ : TUSummaryExtractor(Builder) {}
+
+ static EntityPointerLevel buildEntityPointerLevel(EntityId Entity,
+ unsigned PointerLevel) {
+ return {Entity, PointerLevel};
+ }
+
+ EntityId addEntity(EntityName EN) { return SummaryBuilder.addEntity(EN); }
+
+ std::unique_ptr<UnsafeBufferUsageEntitySummary>
+ extractEntitySummary(const Decl *Contributor, ASTContext &Ctx,
+ llvm::Error &Error);
+
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+};
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h
deleted file mode 100644
index db6c097510a57..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===- UnsafeBufferUsageBuilder.h -------------------------------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include <memory>
-
-namespace clang::ssaf {
-class UnsafeBufferUsageTUSummaryBuilder : public TUSummaryBuilder {
-public:
- static EntityPointerLevel buildEntityPointerLevel(EntityId Entity,
- unsigned PointerLevel) {
- return {Entity, PointerLevel};
- }
-
- static std::unique_ptr<UnsafeBufferUsageEntitySummary>
- buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet &&UnsafeBuffers) {
- return std::make_unique<UnsafeBufferUsageEntitySummary>(
- UnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
- }
-};
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
new file mode 100644
index 0000000000000..34c6dd9b61203
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrameworkAnalyses
+ UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+
+ LINK_LIBS
+ clangAST
+ clangAnalysis
+ clangBasic
+ clangScalableStaticAnalysisFrameworkCore
+
+ DEPENDS
+ )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
new file mode 100644
index 0000000000000..c150b2918db59
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -0,0 +1,281 @@
+//===- UnsafeBufferUsageExtractor.cpp -------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+
+namespace {
+using namespace clang;
+using namespace ssaf;
+
+static bool hasPointerType(const Expr *E) {
+ auto Ty = E->getType();
+ return !Ty.isNull() && !Ty->isFunctionPointerType() &&
+ (Ty->isPointerType() || Ty->isArrayType());
+}
+
+constexpr inline auto buildEntityPointerLevel =
+ UnsafeBufferUsageTUSummaryExtractor::buildEntityPointerLevel;
+
+// Translate a pointer type expression 'E' to a (set of) EntityPointerLevel(s)
+// associated with the declared type of the base address of `E`. If the base
+// address of `E` is not associated with an entity, the translation result is an
+// empty set.
+//
+// The translation is a process of traversing into the pointer 'E' until its
+// base address can be represented by an entity, with the number of dereferences
+// tracked by incrementing the pointer level. Naturally, taking address of, as
+// the inverse operation of dereference, is tracked by decrementing the pointer
+// level.
+//
+// For example, suppose there are pointers and arrays declared as
+// int *ptr, **p1, **p2;
+// int arr[10][10];
+// , the translation of expressions involving these base addresses will be:
+// Translate(ptr + 5) -> {(ptr, 1)}
+// Translate(arr[5]) -> {(arr, 2)}
+// Translate(cond ? p1[5] : p2) -> {(p1, 2), (p2, 1)}
+// Translate(&arr[5]) -> {(arr, 1)}
+class EntityPointerLevelTranslator
+ : ConstStmtVisitor<EntityPointerLevelTranslator,
+ Expected<EntityPointerLevelSet>> {
+ friend class StmtVisitorBase;
+
+ // Fallback method for all unsupported expression kind:
+ llvm::Error fallback(const Stmt *E) {
+ return llvm::createStringError(
+ "unsupported expression kind for translation to "
+ "EntityPointerLevel: %s",
+ E->getStmtClassName());
+ }
+
+ static EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E) {
+ return buildEntityPointerLevel(E.getEntity(), E.getPointerLevel() + 1);
+ }
+
+ static EntityPointerLevel decrementPointerLevel(const EntityPointerLevel &E) {
+ assert(E.getPointerLevel() > 0);
+ return buildEntityPointerLevel(E.getEntity(), E.getPointerLevel() - 1);
+ }
+
+ EntityPointerLevel createEntityPointerLevelFor(const EntityName &Name) {
+ return buildEntityPointerLevel(Extractor.addEntity(Name), 1);
+ }
+
+ // The common helper function for Translate(*base):
+ // Translate(*base) -> Translate(base) with .pointerLevel + 1
+ Expected<EntityPointerLevelSet> translateDereferencePointer(const Expr *Ptr) {
+ assert(hasPointerType(Ptr));
+
+ Expected<EntityPointerLevelSet> SubResult = Visit(Ptr);
+ if (!SubResult)
+ return SubResult.takeError();
+
+ auto Incremented = llvm::map_range(*SubResult, incrementPointerLevel);
+ return EntityPointerLevelSet{Incremented.begin(), Incremented.end()};
+ }
+
+ UnsafeBufferUsageTUSummaryExtractor &Extractor;
+
+public:
+ EntityPointerLevelTranslator(UnsafeBufferUsageTUSummaryExtractor &Extractor)
+ : Extractor(Extractor) {}
+
+ Expected<EntityPointerLevelSet> translate(const Expr *E) { return Visit(E); }
+
+private:
+ Expected<EntityPointerLevelSet> VisitStmt(const Stmt *E) {
+ return fallback(E);
+ }
+
+ // Translate(base + x) -> Translate(base)
+ // Translate(x + base) -> Translate(base)
+ // Translate(base - x) -> Translate(base)
+ // Translate(base {+=, -=, =} x) -> Translate(base)
+ // Translate(x, base) -> Translate(base)
+ Expected<EntityPointerLevelSet> VisitBinaryOperator(const BinaryOperator *E) {
+ switch (E->getOpcode()) {
+ case clang::BO_Add:
+ if (hasPointerType(E->getLHS()))
+ return Visit(E->getLHS());
+ return Visit(E->getRHS());
+ case clang::BO_Sub:
+ case clang::BO_AddAssign:
+ case clang::BO_SubAssign:
+ case clang::BO_Assign:
+ return Visit(E->getLHS());
+ case clang::BO_Comma:
+ return Visit(E->getRHS());
+ default:
+ return fallback(E);
+ }
+ }
+
+ // Translate({++, --}base) -> Translate(base)
+ // Translate(base{++, --}) -> Translate(base)
+ // Translate(*base) -> Translate(base) with .pointerLevel += 1
+ // Translate(&base) -> {}, if Translate(base) is {}
+ // -> Translate(base) with .pointerLevel -= 1
+ Expected<EntityPointerLevelSet> VisitUnaryOperator(const UnaryOperator *E) {
+ switch (E->getOpcode()) {
+ case clang::UO_PostInc:
+ case clang::UO_PostDec:
+ case clang::UO_PreInc:
+ case clang::UO_PreDec:
+ return Visit(E->getSubExpr());
+ case clang::UO_AddrOf: {
+ Expected<EntityPointerLevelSet> SubResult = Visit(E->getSubExpr());
+ if (!SubResult)
+ return SubResult.takeError();
+
+ auto Decremented = llvm::map_range(*SubResult, decrementPointerLevel);
+ return EntityPointerLevelSet{Decremented.begin(), Decremented.end()};
+ }
+ case clang::UO_Deref:
+ return translateDereferencePointer(E->getSubExpr());
+ default:
+ return fallback(E);
+ }
+ }
+
+ // Translate((T*)base) -> Translate(p) if p has pointer type
+ // -> {} otherwise
+ Expected<EntityPointerLevelSet> VisitCastExpr(const CastExpr *E) {
+ if (hasPointerType(E->getSubExpr()))
+ return Visit(E->getSubExpr());
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(f(...)) -> {} if it is an indirect call
+ // -> {(f_return, 1)}, otherwise
+ Expected<EntityPointerLevelSet> VisitCallExpr(const CallExpr *E) {
+ if (auto *FD = E->getDirectCallee())
+ if (auto FDEntityName = getEntityNameForReturn(FD))
+ return EntityPointerLevelSet{
+ createEntityPointerLevelFor(*FDEntityName)};
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(base[x]) -> Translate(*base)
+ Expected<EntityPointerLevelSet>
+ VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
+ return translateDereferencePointer(E->getBase());
+ }
+
+ // Translate(cond ? base1 : base2) := Translate(base1) U Translate(base2)
+ Expected<EntityPointerLevelSet>
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+ Expected<EntityPointerLevelSet> ReT = Visit(E->getTrueExpr());
+ Expected<EntityPointerLevelSet> ReF = Visit(E->getFalseExpr());
+
+ if (ReT && ReF) {
+ ReT->insert(ReF->begin(), ReF->end());
+ return ReT;
+ }
+ if (!ReF && !ReT)
+ return llvm::joinErrors(ReT.takeError(), ReF.takeError());
+ if (!ReF)
+ return ReF.takeError();
+ return ReT.takeError();
+ }
+
+ Expected<EntityPointerLevelSet> VisitParenExpr(const ParenExpr *E) {
+ return Visit(E->getSubExpr());
+ }
+
+ // Translate("string-literal") -> {}
+ // Buffer accesses on string literals are unsafe, but string literals are not
+ // entities so there is no EntityPointerLevel associated with it.
+ Expected<EntityPointerLevelSet> VisitStringLiteral(const StringLiteral *E) {
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(DRE) -> {(Decl, 1)}
+ Expected<EntityPointerLevelSet> VisitDeclRefExpr(const DeclRefExpr *E) {
+ if (auto EntityName = getEntityName(E->getDecl()))
+ return EntityPointerLevelSet{createEntityPointerLevelFor(*EntityName)};
+ return llvm::createStringError(
+ "failed to create entity name from the Decl of " +
+ E->getNameInfo().getAsString());
+ }
+
+ // Translate({., ->}f) -> {(MemberDecl, 1)}
+ Expected<EntityPointerLevelSet> VisitMemberExpr(const MemberExpr *E) {
+ if (auto EntityName = getEntityName(E->getMemberDecl()))
+ return EntityPointerLevelSet{createEntityPointerLevelFor(*EntityName)};
+ return llvm::createStringError(
+ "failed to create entity name from the MemberDecl of " +
+ E->getMemberDecl()->getNameAsString());
+ }
+
+ Expected<EntityPointerLevelSet>
+ VisitOpaqueValueExpr(const OpaqueValueExpr *S) {
+ return Visit(S->getSourceExpr());
+ }
+};
+
+Expected<EntityPointerLevelSet>
+buildEntityPointerLevels(std::set<const Expr *> &&UnsafePointers,
+ UnsafeBufferUsageTUSummaryExtractor &Extractor) {
+ EntityPointerLevelSet Result{};
+ EntityPointerLevelTranslator Translator{Extractor};
+ llvm::Error AllErrors = llvm::ErrorSuccess();
+
+ for (const Expr *Ptr : UnsafePointers) {
+ Expected<EntityPointerLevelSet> Translation = Translator.translate(Ptr);
+
+ if (Translation) {
+ // Filter out those temporary invalid EntityPointerLevels associated with
+ // `&E` pointers:
+ auto FilteredTranslation = llvm::make_filter_range(
+ *Translation, [](const EntityPointerLevel &E) -> bool {
+ return E.getPointerLevel() > 0;
+ });
+ Result.insert(FilteredTranslatio...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/186899
More information about the cfe-commits
mailing list