llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-analysis

Author: Florian Mayer (fmayer)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/164031.diff


3 Files Affected:

- (modified) 
clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h (+16) 
- (modified) clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp 
(+25-8) 
- (modified) 
clang/unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp 
(+72) 


``````````diff
diff --git 
a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h 
b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
index b5bdff2df8ed6..c775d04f0ba8a 100644
--- a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
+++ b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
@@ -58,6 +58,8 @@ namespace clang::dataflow {
 /// for `std::optional`, we assume the (Matcher, TransferFunction) case
 /// with custom handling is ordered early so that these generic cases
 /// do not trigger.
+ast_matchers::StatementMatcher isPointerLikeConstructor();
+ast_matchers::StatementMatcher isSmartPointerLikeConstructor();
 ast_matchers::StatementMatcher isPointerLikeOperatorStar();
 ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar();
 ast_matchers::StatementMatcher isPointerLikeOperatorArrow();
@@ -80,6 +82,8 @@ isSmartPointerLikeGetMethodCall(clang::StringRef MethodName = 
"get");
 const FunctionDecl *
 getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE);
 
+const FunctionDecl *
+getCanonicalSmartPointerLikeOperatorCalleeForType(const CXXRecordDecl *RD);
 /// A transfer function for `operator*` (and `value`) calls that can be
 /// cached. Runs the `InitializeLoc` callback to initialize any new
 /// StorageLocations.
@@ -163,6 +167,18 @@ void transferSmartPointerLikeCachedDeref(
   State.Env.setStorageLocation(*DerefExpr, LocForValue);
 }
 
+template <typename LatticeT>
+void transferSmartPointerLikeConstructor(
+    const CXXConstructExpr *ConstructOperator,
+    RecordStorageLocation *SmartPointerLoc, TransferState<LatticeT> &State,
+    llvm::function_ref<void(QualType, StorageLocation &)> InitializeLoc) {
+  const FunctionDecl *CanonicalCallee =
+      getCanonicalSmartPointerLikeOperatorCalleeForType(
+          ConstructOperator->getType()->getAsCXXRecordDecl());
+  State.Lattice.getOrCreateConstMethodReturnStorageLocation(
+      *SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc);
+}
+
 template <typename LatticeT>
 void transferSmartPointerLikeCachedGet(
     const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
diff --git a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp 
b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
index d87b2e6f03857..e639119e1a290 100644
--- a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
+++ b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
@@ -129,6 +129,12 @@ AST_MATCHER(clang::CXXRecordDecl, pointerClass) {
 
 namespace clang::dataflow {
 
+ast_matchers::StatementMatcher isSmartPointerLikeConstructor() {
+  using namespace ast_matchers;
+  return cxxConstructExpr(hasType(hasCanonicalType(qualType(
+      hasDeclaration(cxxRecordDecl(smartPointerClassWithGetOrValue()))))));
+}
+
 ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar() {
   return cxxOperatorCallExpr(
       hasOverloadedOperatorName("*"),
@@ -145,6 +151,12 @@ ast_matchers::StatementMatcher 
isSmartPointerLikeOperatorArrow() {
                            ofClass(smartPointerClassWithGetOrValue()))));
 }
 
+ast_matchers::StatementMatcher isPointerLikeConstructor() {
+  using namespace ast_matchers;
+  return cxxConstructExpr(hasType(hasCanonicalType(
+      qualType(hasDeclaration(cxxRecordDecl(pointerClass()))))));
+}
+
 ast_matchers::StatementMatcher isPointerLikeOperatorStar() {
   return cxxOperatorCallExpr(
       hasOverloadedOperatorName("*"),
@@ -177,15 +189,8 @@ isSmartPointerLikeGetMethodCall(clang::StringRef 
MethodName) {
 }
 
 const FunctionDecl *
-getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE) {
+getCanonicalSmartPointerLikeOperatorCalleeForType(const CXXRecordDecl *RD) {
   const FunctionDecl *CanonicalCallee = nullptr;
-  const CXXMethodDecl *Callee =
-      cast_or_null<CXXMethodDecl>(CE->getDirectCallee());
-  if (Callee == nullptr)
-    return nullptr;
-  const CXXRecordDecl *RD = Callee->getParent();
-  if (RD == nullptr)
-    return nullptr;
   for (const auto *MD : RD->methods()) {
     if (MD->getOverloadedOperator() == OO_Star && MD->isConst() &&
         MD->getNumParams() == 0 && MD->getReturnType()->isReferenceType()) {
@@ -196,4 +201,16 @@ getCanonicalSmartPointerLikeOperatorCallee(const CallExpr 
*CE) {
   return CanonicalCallee;
 }
 
+const FunctionDecl *
+getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE) {
+  const CXXMethodDecl *Callee =
+      cast_or_null<CXXMethodDecl>(CE->getDirectCallee());
+  if (Callee == nullptr)
+    return nullptr;
+  const CXXRecordDecl *RD = Callee->getParent();
+  if (RD == nullptr)
+    return nullptr;
+  return getCanonicalSmartPointerLikeOperatorCalleeForType(RD);
+}
+
 } // namespace clang::dataflow
diff --git 
a/clang/unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp
index 5d3d5b0cfea09..05c66b0847c7a 100644
--- a/clang/unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp
@@ -64,6 +64,15 @@ TEST(SmartPointerAccessorCachingTest, 
MatchesClassWithStarArrowGet) {
                       isSmartPointerLikeOperatorArrow()));
   EXPECT_TRUE(matches(Decls, "int target(UniquePtrAlias<S> P) { return P->i; 
}",
                       isPointerLikeOperatorArrow()));
+
+  EXPECT_TRUE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_TRUE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, MatchesClassWithStarArrow) {
@@ -101,6 +110,15 @@ TEST(SmartPointerAccessorCachingTest, 
MatchesClassWithStarArrow) {
                        isSmartPointerLikeOperatorArrow()));
   EXPECT_TRUE(matches(Decls, "int target(UniquePtrAlias<S> P) { return P->i; 
}",
                       isPointerLikeOperatorArrow()));
+
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_TRUE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, NoMatchIfUnexpectedReturnTypes) {
@@ -141,6 +159,15 @@ TEST(SmartPointerAccessorCachingTest, 
NoMatchIfUnexpectedReturnTypes) {
   EXPECT_TRUE(matches(Decls,
                       "int target(std::unique_ptr<S, S> P) { return P->i; }",
                       isPointerLikeOperatorArrow()));
+
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S, T>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S, T>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, NoMatchIfBinaryStar) {
@@ -163,6 +190,15 @@ TEST(SmartPointerAccessorCachingTest, NoMatchIfBinaryStar) 
{
   EXPECT_FALSE(
       matches(Decls, "int target(std::unique_ptr<S> P) { return (P * 10).i; }",
               isPointerLikeOperatorStar()));
+
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, NoMatchIfNoConstOverloads) {
@@ -196,6 +232,15 @@ TEST(SmartPointerAccessorCachingTest, 
NoMatchIfNoConstOverloads) {
   EXPECT_FALSE(
       matches(Decls, "int target(std::unique_ptr<S> P) { return P.get()->i; }",
               isSmartPointerLikeGetMethodCall()));
+
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, NoMatchIfNoStarMethod) {
@@ -221,6 +266,15 @@ TEST(SmartPointerAccessorCachingTest, 
NoMatchIfNoStarMethod) {
   EXPECT_FALSE(matches(Decls,
                        "int target(std::unique_ptr<S> P) { return P->i; }",
                        isSmartPointerLikeGetMethodCall()));
+
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_FALSE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, MatchesWithValueAndNonConstOverloads) {
@@ -276,6 +330,13 @@ TEST(SmartPointerAccessorCachingTest, 
MatchesWithValueAndNonConstOverloads) {
       Decls,
       "int target(const std::optional<S> &Const) { return Const.value().i; }",
       isSmartPointerLikeValueMethodCall()));
+
+  EXPECT_TRUE(matches(
+      Decls, "std::optional<S>& Helper(); int target() { auto S = Helper(); }",
+      isSmartPointerLikeConstructor()));
+  EXPECT_TRUE(matches(
+      Decls, "std::optional<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, MatchesWithTypeAliases) {
@@ -329,6 +390,9 @@ TEST(SmartPointerAccessorCachingTest, 
MatchesWithTypeAliases) {
   EXPECT_TRUE(matches(
       Decls, "int target(const HasGetAndValue<S> &Const) { return Const->i; }",
       isPointerLikeOperatorArrow()));
+  EXPECT_TRUE(matches(
+      Decls, "HasGetAndValue<S>& Helper(); int target() { auto S = Helper(); 
}",
+      isPointerLikeConstructor()));
 
   EXPECT_TRUE(matches(
       Decls,
@@ -346,6 +410,9 @@ TEST(SmartPointerAccessorCachingTest, 
MatchesWithTypeAliases) {
       Decls,
       "int target(const HasGetAndValue<S> &Const) { return Const.get()->i; }",
       isSmartPointerLikeGetMethodCall()));
+  EXPECT_TRUE(matches(
+      Decls, "HasGetAndValue<S>& Helper(); int target() { auto S = Helper(); 
}",
+      isSmartPointerLikeConstructor()));
 }
 
 TEST(SmartPointerAccessorCachingTest, Renamed) {
@@ -390,6 +457,11 @@ TEST(SmartPointerAccessorCachingTest, Renamed) {
 
   EXPECT_TRUE(matches(Decls, "int target(UniquePtrAlias<S> P) { return P->i; 
}",
                       isPointerLikeOperatorArrow()));
+
+  EXPECT_TRUE(matches(
+      Decls,
+      "std::unique_ptr<S>& Helper(); int target() { auto S = Helper(); }",
+      isPointerLikeConstructor()));
 }
 
 } // namespace

``````````

</details>


https://github.com/llvm/llvm-project/pull/164031
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to