[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand closed https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread Samira Bazuzi via cfe-commits

https://github.com/bazuzi updated 
https://github.com/llvm/llvm-project/pull/88754

>From 223d4c48abf27c8b0949ac1520b66ef32cbd63c1 Mon Sep 17 00:00:00 2001
From: Samira Bazuzi 
Date: Fri, 12 Apr 2024 12:18:44 -0400
Subject: [PATCH 1/4] [clang][dataflow] Expose fields, globals, and functions
 referenced.

Exposes the collection functionality, but does not alter it beyond using
a return value instead of output parameters. Also relocates underlying
and related functions and a class from DataflowEnvironment's files to
DataflowAnalysisContext's files, as no Environment is needed.
---
 .../FlowSensitive/DataflowAnalysisContext.h   |  46 +
 .../FlowSensitive/DataflowEnvironment.h   |  36 
 .../FlowSensitive/DataflowAnalysisContext.cpp | 174 +
 .../FlowSensitive/DataflowEnvironment.cpp | 176 +-
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |   1 +
 5 files changed, 225 insertions(+), 208 deletions(-)

diff --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 909a91059438ca..a34e5f603eb396 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -62,6 +62,52 @@ FieldSet getObjectFields(QualType Type);
 bool containsSameFields(const FieldSet ,
 const RecordStorageLocation::FieldToLoc );
 
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+/// Helper class for initialization of a record with an `InitListExpr`.
+/// `InitListExpr::inits()` contains the initializers for both the base classes
+/// and the fields of the record; this helper class separates these out into 
two
+/// different lists. In addition, it deals with special cases associated with
+/// unions.
+class RecordInitListHelper {
+public:
+  // `InitList` must have record type.
+  RecordInitListHelper(const InitListExpr *InitList);
+
+  // Base classes with their associated initializer expressions.
+  ArrayRef> base_inits() const {
+return BaseInits;
+  }
+
+  // Fields with their associated initializer expressions.
+  ArrayRef> field_inits() const {
+return FieldInits;
+  }
+
+private:
+  SmallVector> BaseInits;
+  SmallVector> FieldInits;
+
+  // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a
+  // member variable because we store a pointer to it in `FieldInits`.
+  std::optional ImplicitValueInitForUnion;
+};
+
+struct FieldsGlobalsAndFuncs {
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.
+  llvm::DenseSet Globals;
+  llvm::DenseSet Funcs;
+};
+
+FieldsGlobalsAndFuncs getFieldsGlobalsAndFuncs(const FunctionDecl );
+
 struct ContextSensitiveOptions {
   /// The maximum depth to analyze. A value of zero is equivalent to disabling
   /// context-sensitive analysis entirely.
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 706664d7db1c25..4277792219c0af 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -775,42 +775,6 @@ RecordStorageLocation *getImplicitObjectLocation(const 
CXXMemberCallExpr ,
 RecordStorageLocation *getBaseObjectLocation(const MemberExpr ,
  const Environment );
 
-/// Returns the fields of a `RecordDecl` that are initialized by an
-/// `InitListExpr`, in the order in which they appear in
-/// `InitListExpr::inits()`.
-/// `Init->getType()` must be a record type.
-std::vector
-getFieldsForInitListExpr(const InitListExpr *InitList);
-
-/// Helper class for initialization of a record with an `InitListExpr`.
-/// `InitListExpr::inits()` contains the initializers for both the base classes
-/// and the fields of the record; this helper class separates these out into 
two
-/// different lists. In addition, it deals with special cases associated with
-/// unions.
-class RecordInitListHelper {
-public:
-  // `InitList` must have record type.
-  RecordInitListHelper(const InitListExpr *InitList);
-
-  // Base classes with their associated initializer expressions.
-  ArrayRef> base_inits() const {
-return BaseInits;
-  }
-
-  // Fields with their associated initializer expressions.
-  ArrayRef> field_inits() const {
-return FieldInits;
-  }
-
-private:
-  SmallVector> BaseInits;
-  SmallVector> FieldInits;
-
-  // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a
-  // member variable because we store a pointer to it in 

[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to
+/// flow-sensitive analysis, and should be ignored as they will effectively not
+/// exist.
+///
+///   * `ParenExpr` - The CFG takes the operator precedence into account, but
+///   otherwise omits the node afterwards.
+///
+///   * `ExprWithCleanups` - The CFG will generate the appropriate calls to
+///   destructors and then omit the node.
+///
+const Expr (const Expr );
+const Stmt (const Stmt );
+
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector;
+
+/// Returns the set of all fields in the type.
+FieldSet getObjectFields(QualType Type);
+
+/// Returns whether `Fields` and `FieldLocs` contain the same fields.
+bool containsSameFields(const FieldSet ,
+const RecordStorageLocation::FieldToLoc );
+
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+// A collection of several types of declarations, all referenced from the same
+// function.
+struct ReferencedDecls {
+  // Fields includes non-static data members.
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.
+  llvm::DenseSet Globals;
+  // Functions includes free functions and member functions which are
+  // referenced, but not necessarily called.
+  llvm::DenseSet Functions;
+};
+
+/// Collects and returns fields, global variables and functions that are
+/// declared in or referenced from `FD`.

martinboehme wrote:

```suggestion
/// Returns declarations that are declared in or referenced from `FD`.
```

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to

martinboehme wrote:

```suggestion
namespace dataflow {

/// Skip past nodes that the CFG does not emit. These nodes are invisible to
```

This is the usual style in the project. (Otherwise, the namespace looks as if 
it belongs more closely to the following function than that function belongs to 
the others.)

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,214 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/ASTOps.h"
+#include "clang/AST/ComputeDependence.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include 
+#include 
+#include 
+
+#define DEBUG_TYPE "dataflow"
+
+namespace clang::dataflow {
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList) {
+  const RecordDecl *RD = InitList->getType()->getAsRecordDecl();
+  assert(RD != nullptr);
+
+  std::vector Fields;
+
+  if (InitList->getType()->isUnionType()) {
+Fields.push_back(InitList->getInitializedFieldInUnion());
+return Fields;
+  }
+
+  // Unnamed bitfields are only used for padding and do not appear in
+  // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
+  // field list, and we thus need to remove them before mapping inits to
+  // fields to avoid mapping inits to the wrongs fields.
+  llvm::copy_if(
+  RD->fields(), std::back_inserter(Fields),
+  [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
+  return Fields;
+}
+
+static void insertIfGlobal(const Decl ,
+   llvm::DenseSet ) {
+  if (auto *V = dyn_cast())
+if (V->hasGlobalStorage())
+  Vars.insert(V);
+}
+
+static void insertIfFunction(const Decl ,
+ llvm::DenseSet ) {
+  if (auto *FD = dyn_cast())
+Funcs.insert(FD);
+}
+
+static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr ) {
+  // Use getCalleeDecl instead of getMethodDecl in order to handle
+  // pointer-to-member calls.
+  const auto *MethodDecl = dyn_cast_or_null(C.getCalleeDecl());
+  if (!MethodDecl)
+return nullptr;
+  auto *Body = dyn_cast_or_null(MethodDecl->getBody());
+  if (!Body || Body->size() != 1)
+return nullptr;
+  if (auto *RS = dyn_cast(*Body->body_begin()))
+if (auto *Return = RS->getRetValue())
+  return dyn_cast(Return->IgnoreParenImpCasts());
+  return nullptr;
+}
+
+static void getReferencedDecls(const Decl , FieldSet ,
+   llvm::DenseSet ,
+   llvm::DenseSet ) {

martinboehme wrote:

Suggest a `ReferencedDecls` parameter instead of passing `Fields`, `Vars`, and 
`Funcs` separately.

```suggestion
static void getReferencedDecls(const Decl , ReferencedDecls ) {
```

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -66,6 +66,35 @@ inline bool recordsEqual(const RecordStorageLocation ,
   return recordsEqual(Loc1, Env, Loc2, Env);
 }
 
+/// Helper class for initialization of a record with an `InitListExpr`.
+/// `InitListExpr::inits()` contains the initializers for both the base classes
+/// and the fields of the record; this helper class separates these out into 
two
+/// different lists. In addition, it deals with special cases associated with
+/// unions.
+class RecordInitListHelper {
+public:
+  // `InitList` must have record type.
+  RecordInitListHelper(const InitListExpr *InitList);
+
+  // Base classes with their associated initializer expressions.
+  ArrayRef> base_inits() const {
+return BaseInits;
+  }
+
+  // Fields with their associated initializer expressions.
+  ArrayRef> field_inits() const {
+return FieldInits;
+  }
+
+private:
+  SmallVector> BaseInits;
+  SmallVector> FieldInits;
+
+  // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a
+  // member variable because we store a pointer to it in `FieldInits`.
+  std::optional ImplicitValueInitForUnion;
+};
+

martinboehme wrote:

I think this would fit better in ASTOps.h as well.

The intent of RecordOps.h is to contain functions that operate on our 
representation of record objects, i.e. `RecordStorageLocation`s. 
`RecordInitListHelper`, on the other hand, is just a more convenient way of 
accessing the initializers in an `InitListExpr` and so seems a better fit in 
ASTOps.h. (Note also that the closely related `getFieldsForInitListExpr()` 
already lives there.)

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -648,36 +563,13 @@ void Environment::initialize() {
 void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) {
   assert(FuncDecl->doesThisDeclarationHaveABody());
 
-  FieldSet Fields;
-  llvm::DenseSet Vars;
-  llvm::DenseSet Funcs;
-
-  // Look for global variable and field references in the
-  // constructor-initializers.
-  if (const auto *CtorDecl = dyn_cast(FuncDecl)) {
-for (const auto *Init : CtorDecl->inits()) {
-  if (Init->isMemberInitializer()) {
-Fields.insert(Init->getMember());
-  } else if (Init->isIndirectMemberInitializer()) {
-for (const auto *I : Init->getIndirectMember()->chain())
-  Fields.insert(cast(I));
-  }
-  const Expr *E = Init->getInit();
-  assert(E != nullptr);
-  getFieldsGlobalsAndFuncs(*E, Fields, Vars, Funcs);
-}
-// Add all fields mentioned in default member initializers.
-for (const FieldDecl *F : CtorDecl->getParent()->fields())
-  if (const auto *I = F->getInClassInitializer())
-  getFieldsGlobalsAndFuncs(*I, Fields, Vars, Funcs);
-  }
-  getFieldsGlobalsAndFuncs(*FuncDecl->getBody(), Fields, Vars, Funcs);
+  ReferencedDecls FGF = getReferencedDecls(*FuncDecl);

martinboehme wrote:

```suggestion
  ReferencedDecls Referenced = getReferencedDecls(*FuncDecl);
```

(Now that the struct is called `ReferencedDecls`, it's not clear why the 
variable should be called `FGF`.)

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits




martinboehme wrote:

Can you add this file to clang/docs/tools/clang-formatted-files.txt?

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits

https://github.com/martinboehme approved this pull request.

Thanks for the cleanup!

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,214 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/ASTOps.h"
+#include "clang/AST/ComputeDependence.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include 
+#include 
+#include 
+
+#define DEBUG_TYPE "dataflow"
+
+namespace clang::dataflow {
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList) {
+  const RecordDecl *RD = InitList->getType()->getAsRecordDecl();
+  assert(RD != nullptr);
+
+  std::vector Fields;
+
+  if (InitList->getType()->isUnionType()) {
+Fields.push_back(InitList->getInitializedFieldInUnion());
+return Fields;
+  }
+
+  // Unnamed bitfields are only used for padding and do not appear in
+  // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
+  // field list, and we thus need to remove them before mapping inits to
+  // fields to avoid mapping inits to the wrongs fields.
+  llvm::copy_if(
+  RD->fields(), std::back_inserter(Fields),
+  [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
+  return Fields;
+}
+
+static void insertIfGlobal(const Decl ,
+   llvm::DenseSet ) {
+  if (auto *V = dyn_cast())
+if (V->hasGlobalStorage())
+  Vars.insert(V);
+}
+
+static void insertIfFunction(const Decl ,
+ llvm::DenseSet ) {
+  if (auto *FD = dyn_cast())
+Funcs.insert(FD);
+}
+
+static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr ) {
+  // Use getCalleeDecl instead of getMethodDecl in order to handle
+  // pointer-to-member calls.
+  const auto *MethodDecl = dyn_cast_or_null(C.getCalleeDecl());
+  if (!MethodDecl)
+return nullptr;
+  auto *Body = dyn_cast_or_null(MethodDecl->getBody());
+  if (!Body || Body->size() != 1)
+return nullptr;
+  if (auto *RS = dyn_cast(*Body->body_begin()))
+if (auto *Return = RS->getRetValue())
+  return dyn_cast(Return->IgnoreParenImpCasts());
+  return nullptr;
+}
+
+static void getReferencedDecls(const Decl , FieldSet ,
+   llvm::DenseSet ,
+   llvm::DenseSet ) {
+  insertIfGlobal(D, Vars);
+  insertIfFunction(D, Funcs);
+  if (const auto *Decomp = dyn_cast())
+for (const auto *B : Decomp->bindings())
+  if (auto *ME = dyn_cast_or_null(B->getBinding()))
+// FIXME: should we be using `E->getFoundDecl()`?
+if (const auto *FD = dyn_cast(ME->getMemberDecl()))
+  Fields.insert(FD);
+}
+
+/// Traverses `S` and inserts into `Fields`, `Vars` and `Funcs` any fields,
+/// global variables and functions that are declared in or referenced from
+/// sub-statements.
+static void getReferencedDecls(const Stmt , FieldSet ,

martinboehme wrote:

Again, suggest a `ReferencedDecls` parameter. This would also make the multiple 
recursive calls less verbose.

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,214 @@
+//===-- ASTOps.h ---*- C++ -*-===//

martinboehme wrote:

```suggestion
//===-- ASTOps.cpp -*- C++ -*-===//
```

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to
+/// flow-sensitive analysis, and should be ignored as they will effectively not
+/// exist.
+///
+///   * `ParenExpr` - The CFG takes the operator precedence into account, but
+///   otherwise omits the node afterwards.
+///
+///   * `ExprWithCleanups` - The CFG will generate the appropriate calls to
+///   destructors and then omit the node.
+///
+const Expr (const Expr );
+const Stmt (const Stmt );
+
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector;
+
+/// Returns the set of all fields in the type.
+FieldSet getObjectFields(QualType Type);
+
+/// Returns whether `Fields` and `FieldLocs` contain the same fields.
+bool containsSameFields(const FieldSet ,
+const RecordStorageLocation::FieldToLoc );
+
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+// A collection of several types of declarations, all referenced from the same
+// function.
+struct ReferencedDecls {
+  // Fields includes non-static data members.
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.
+  llvm::DenseSet Globals;
+  // Functions includes free functions and member functions which are
+  // referenced, but not necessarily called.

martinboehme wrote:

```suggestion
  // Free functions and member functions which are referenced (but not 
necessarily called).
```

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to
+/// flow-sensitive analysis, and should be ignored as they will effectively not
+/// exist.
+///
+///   * `ParenExpr` - The CFG takes the operator precedence into account, but
+///   otherwise omits the node afterwards.
+///
+///   * `ExprWithCleanups` - The CFG will generate the appropriate calls to
+///   destructors and then omit the node.
+///
+const Expr (const Expr );
+const Stmt (const Stmt );
+
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector;
+
+/// Returns the set of all fields in the type.
+FieldSet getObjectFields(QualType Type);
+
+/// Returns whether `Fields` and `FieldLocs` contain the same fields.
+bool containsSameFields(const FieldSet ,
+const RecordStorageLocation::FieldToLoc );
+
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+// A collection of several types of declarations, all referenced from the same
+// function.
+struct ReferencedDecls {
+  // Fields includes non-static data members.

martinboehme wrote:

```suggestion
  /// Non-static member variables.
```

*  Make this a Doxygen comment (three slashes)
*  No need to repeat the name of the declaration you're documenting
*  "includes" could be interpreted as "in addition to something else, includes 
non-static data members", so just dropping it.
*  Standard C++ terminology is "member variables"

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to
+/// flow-sensitive analysis, and should be ignored as they will effectively not
+/// exist.
+///
+///   * `ParenExpr` - The CFG takes the operator precedence into account, but
+///   otherwise omits the node afterwards.
+///
+///   * `ExprWithCleanups` - The CFG will generate the appropriate calls to
+///   destructors and then omit the node.
+///
+const Expr (const Expr );
+const Stmt (const Stmt );
+
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector;
+
+/// Returns the set of all fields in the type.
+FieldSet getObjectFields(QualType Type);
+
+/// Returns whether `Fields` and `FieldLocs` contain the same fields.
+bool containsSameFields(const FieldSet ,
+const RecordStorageLocation::FieldToLoc );
+
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+// A collection of several types of declarations, all referenced from the same
+// function.
+struct ReferencedDecls {
+  // Fields includes non-static data members.
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.
+  llvm::DenseSet Globals;
+  // Functions includes free functions and member functions which are
+  // referenced, but not necessarily called.
+  llvm::DenseSet Functions;
+};
+
+/// Collects and returns fields, global variables and functions that are
+/// declared in or referenced from `FD`.
+ReferencedDecls getReferencedDecls(const FunctionDecl );
+} // namespace dataflow

martinboehme wrote:

```suggestion
ReferencedDecls getReferencedDecls(const FunctionDecl );

} // namespace dataflow
```

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits




martinboehme wrote:

Can you add this file to clang/docs/tools/clang-formatted-files.txt?

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits


@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to
+/// flow-sensitive analysis, and should be ignored as they will effectively not
+/// exist.
+///
+///   * `ParenExpr` - The CFG takes the operator precedence into account, but
+///   otherwise omits the node afterwards.
+///
+///   * `ExprWithCleanups` - The CFG will generate the appropriate calls to
+///   destructors and then omit the node.
+///
+const Expr (const Expr );
+const Stmt (const Stmt );
+
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector;
+
+/// Returns the set of all fields in the type.
+FieldSet getObjectFields(QualType Type);
+
+/// Returns whether `Fields` and `FieldLocs` contain the same fields.
+bool containsSameFields(const FieldSet ,
+const RecordStorageLocation::FieldToLoc );
+
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+// A collection of several types of declarations, all referenced from the same
+// function.
+struct ReferencedDecls {
+  // Fields includes non-static data members.
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.

martinboehme wrote:

```suggestion
  // All variables with static storage duration, notably including static 
member variables and static
  // variables declared within a function.
```

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-16 Thread via cfe-commits

https://github.com/martinboehme edited 
https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-15 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand approved this pull request.

Thanks!

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-15 Thread Samira Bazuzi via cfe-commits

bazuzi wrote:

@ymand @martinboehme Apologies for the broken chains of comments; can you take 
another look?

https://github.com/llvm/llvm-project/pull/88754
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-15 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-analysis

Author: Samira Bazuzi (bazuzi)


Changes

Moves free functions from DataflowEnvironment.h/cc and 
DataflowAnalysisContext.h/cc to RecordOps and a new ASTOps and exposes them as 
needed for current use and to expose getReferencedDecls for out-of-tree use.

Minimal change in functionality, only to modify the return type of 
getReferenceDecls to return the collected decls instead of using output params.

Tested with `ninja check-clang-tooling`.


This started as #88534, but I screwed up the push of changes after a 
first round of comments and needed to close that PR to avoid spam for recent 
commit authors. I believe all of the first round comments have been addressed 
and should be considered marked "Done" and resolved.

---

Patch is 31.75 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/88754.diff


10 Files Affected:

- (added) clang/include/clang/Analysis/FlowSensitive/ASTOps.h (+75) 
- (modified) 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h (+1-27) 
- (modified) clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
(-36) 
- (modified) clang/include/clang/Analysis/FlowSensitive/RecordOps.h (+29) 
- (added) clang/lib/Analysis/FlowSensitive/ASTOps.cpp (+214) 
- (modified) clang/lib/Analysis/FlowSensitive/CMakeLists.txt (+1) 
- (modified) clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
(+1-52) 
- (modified) clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (+6-172) 
- (modified) clang/lib/Analysis/FlowSensitive/RecordOps.cpp (+37) 
- (modified) clang/lib/Analysis/FlowSensitive/Transfer.cpp (+2) 


``diff
diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h 
b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
new file mode 100644
index 00..5e3c0f21f5e863
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
@@ -0,0 +1,75 @@
+//===-- ASTOps.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
+//
+//===--===//
+//
+//  Operations on AST nodes that are used in flow-sensitive analysis.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace dataflow {
+/// Skip past nodes that the CFG does not emit. These nodes are invisible to
+/// flow-sensitive analysis, and should be ignored as they will effectively not
+/// exist.
+///
+///   * `ParenExpr` - The CFG takes the operator precedence into account, but
+///   otherwise omits the node afterwards.
+///
+///   * `ExprWithCleanups` - The CFG will generate the appropriate calls to
+///   destructors and then omit the node.
+///
+const Expr (const Expr );
+const Stmt (const Stmt );
+
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector;
+
+/// Returns the set of all fields in the type.
+FieldSet getObjectFields(QualType Type);
+
+/// Returns whether `Fields` and `FieldLocs` contain the same fields.
+bool containsSameFields(const FieldSet ,
+const RecordStorageLocation::FieldToLoc );
+
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+// A collection of several types of declarations, all referenced from the same
+// function.
+struct ReferencedDecls {
+  // Fields includes non-static data members.
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.
+  llvm::DenseSet Globals;
+  // Functions includes free functions and member functions which are
+  // referenced, but not necessarily called.
+  llvm::DenseSet Functions;
+};
+
+/// Collects and returns fields, global variables and functions that are
+/// declared in or referenced from `FD`.
+ReferencedDecls getReferencedDecls(const FunctionDecl );
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
diff --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 

[clang] [clang][dataflow] Expose getReferencedDecls and relocate free functions. (PR #88754)

2024-04-15 Thread Samira Bazuzi via cfe-commits

https://github.com/bazuzi created 
https://github.com/llvm/llvm-project/pull/88754

Moves free functions from DataflowEnvironment.h/cc and 
DataflowAnalysisContext.h/cc to RecordOps and a new ASTOps and exposes them as 
needed for current use and to expose getReferencedDecls for out-of-tree use.

Minimal change in functionality, only to modify the return type of 
getReferenceDecls to return the collected decls instead of using output params.

Tested with `ninja check-clang-tooling`.


This started as #88534, but I screwed up the push of changes after a first 
round of comments and needed to close that PR to avoid spam for recent commit 
authors. I believe all of the first round comments have been addressed and 
should be considered marked "Done" and resolved.

>From 223d4c48abf27c8b0949ac1520b66ef32cbd63c1 Mon Sep 17 00:00:00 2001
From: Samira Bazuzi 
Date: Fri, 12 Apr 2024 12:18:44 -0400
Subject: [PATCH 1/3] [clang][dataflow] Expose fields, globals, and functions
 referenced.

Exposes the collection functionality, but does not alter it beyond using
a return value instead of output parameters. Also relocates underlying
and related functions and a class from DataflowEnvironment's files to
DataflowAnalysisContext's files, as no Environment is needed.
---
 .../FlowSensitive/DataflowAnalysisContext.h   |  46 +
 .../FlowSensitive/DataflowEnvironment.h   |  36 
 .../FlowSensitive/DataflowAnalysisContext.cpp | 174 +
 .../FlowSensitive/DataflowEnvironment.cpp | 176 +-
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |   1 +
 5 files changed, 225 insertions(+), 208 deletions(-)

diff --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 909a91059438ca..a34e5f603eb396 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -62,6 +62,52 @@ FieldSet getObjectFields(QualType Type);
 bool containsSameFields(const FieldSet ,
 const RecordStorageLocation::FieldToLoc );
 
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
+
+/// Helper class for initialization of a record with an `InitListExpr`.
+/// `InitListExpr::inits()` contains the initializers for both the base classes
+/// and the fields of the record; this helper class separates these out into 
two
+/// different lists. In addition, it deals with special cases associated with
+/// unions.
+class RecordInitListHelper {
+public:
+  // `InitList` must have record type.
+  RecordInitListHelper(const InitListExpr *InitList);
+
+  // Base classes with their associated initializer expressions.
+  ArrayRef> base_inits() const {
+return BaseInits;
+  }
+
+  // Fields with their associated initializer expressions.
+  ArrayRef> field_inits() const {
+return FieldInits;
+  }
+
+private:
+  SmallVector> BaseInits;
+  SmallVector> FieldInits;
+
+  // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a
+  // member variable because we store a pointer to it in `FieldInits`.
+  std::optional ImplicitValueInitForUnion;
+};
+
+struct FieldsGlobalsAndFuncs {
+  FieldSet Fields;
+  // Globals includes all variables with global storage, notably including
+  // static data members and static variables declared within a function.
+  llvm::DenseSet Globals;
+  llvm::DenseSet Funcs;
+};
+
+FieldsGlobalsAndFuncs getFieldsGlobalsAndFuncs(const FunctionDecl );
+
 struct ContextSensitiveOptions {
   /// The maximum depth to analyze. A value of zero is equivalent to disabling
   /// context-sensitive analysis entirely.
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 706664d7db1c25..4277792219c0af 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -775,42 +775,6 @@ RecordStorageLocation *getImplicitObjectLocation(const 
CXXMemberCallExpr ,
 RecordStorageLocation *getBaseObjectLocation(const MemberExpr ,
  const Environment );
 
-/// Returns the fields of a `RecordDecl` that are initialized by an
-/// `InitListExpr`, in the order in which they appear in
-/// `InitListExpr::inits()`.
-/// `Init->getType()` must be a record type.
-std::vector
-getFieldsForInitListExpr(const InitListExpr *InitList);
-
-/// Helper class for initialization of a record with an `InitListExpr`.
-/// `InitListExpr::inits()` contains the initializers for both the base classes
-/// and the fields of the record; this helper class separates these out into 
two
-///