[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-19 Thread Ding Fei via cfe-commits

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-18 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0d6d52365a5d31045c347412c3a0fe8be7119006 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:33:29 +0800
Subject: [PATCH 1/6] [ASTImporter] Fix infinite recurse on return type
 declared inside body (#68775)

Lambda without trailing auto could has return type declared
inside the body too.
---
 clang/docs/ReleaseNotes.rst |  2 ++
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c19ad9fba58f37..7a623c6be72fd2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,8 @@ Bug Fixes to AST Handling
 Miscellaneous Bug Fixes
 ^^^
 
+- Fixed an infinite recursion on return type declared inside body (#GH68775).
+
 Miscellaneous Clang Crashes Fixed
 ^
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

>From 3f1d714a2aa4b236afe9bb1384be073fb155a2b8 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 08:56:56 +0800
Subject: [PATCH 2/6] Limit TypeVisitor checking to 'auto' and lambda
 definition only

1. Fix potential perf regression;
2. Fix comment.
---
 clang/lib/AST/ASTImporter.cpp | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3bbd6ebaf1..d98cb80c349db2 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3647,17 +3647,25 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
 bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = 

[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-18 Thread Ding Fei via cfe-commits


@@ -3647,15 +3647,28 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  auto IsCXX11LambdaWithouTrailingReturn = [&]() {
+if (!Importer.FromContext.getLangOpts().CPlusPlus11)

danix800 wrote:

These `CPlusPlus` / `CPlusPlus11` / `CPlusPlus14` options are really misleading 
if no comments explaining how they works. Thanks for pointing this out!

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0d6d52365a5d31045c347412c3a0fe8be7119006 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:33:29 +0800
Subject: [PATCH 1/5] [ASTImporter] Fix infinite recurse on return type
 declared inside body (#68775)

Lambda without trailing auto could has return type declared
inside the body too.
---
 clang/docs/ReleaseNotes.rst |  2 ++
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c19ad9fba58f37..7a623c6be72fd2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,8 @@ Bug Fixes to AST Handling
 Miscellaneous Bug Fixes
 ^^^
 
+- Fixed an infinite recursion on return type declared inside body (#GH68775).
+
 Miscellaneous Clang Crashes Fixed
 ^
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

>From 3f1d714a2aa4b236afe9bb1384be073fb155a2b8 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 08:56:56 +0800
Subject: [PATCH 2/5] Limit TypeVisitor checking to 'auto' and lambda
 definition only

1. Fix potential perf regression;
2. Fix comment.
---
 clang/lib/AST/ASTImporter.cpp | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3bbd6ebaf1..d98cb80c349db2 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3647,17 +3647,25 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
 bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = 

[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0d6d52365a5d31045c347412c3a0fe8be7119006 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:33:29 +0800
Subject: [PATCH 1/4] [ASTImporter] Fix infinite recurse on return type
 declared inside body (#68775)

Lambda without trailing auto could has return type declared
inside the body too.
---
 clang/docs/ReleaseNotes.rst |  2 ++
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c19ad9fba58f37..7a623c6be72fd2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,8 @@ Bug Fixes to AST Handling
 Miscellaneous Bug Fixes
 ^^^
 
+- Fixed an infinite recursion on return type declared inside body (#GH68775).
+
 Miscellaneous Clang Crashes Fixed
 ^
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

>From 3f1d714a2aa4b236afe9bb1384be073fb155a2b8 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 08:56:56 +0800
Subject: [PATCH 2/4] Limit TypeVisitor checking to 'auto' and lambda
 definition only

1. Fix potential perf regression;
2. Fix comment.
---
 clang/lib/AST/ASTImporter.cpp | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3bbd6ebaf1..d98cb80c349db2 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3647,17 +3647,25 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
 bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = 

[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0d6d52365a5d31045c347412c3a0fe8be7119006 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:33:29 +0800
Subject: [PATCH 1/3] [ASTImporter] Fix infinite recurse on return type
 declared inside body (#68775)

Lambda without trailing auto could has return type declared
inside the body too.
---
 clang/docs/ReleaseNotes.rst |  2 ++
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c19ad9fba58f37..7a623c6be72fd2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,8 @@ Bug Fixes to AST Handling
 Miscellaneous Bug Fixes
 ^^^
 
+- Fixed an infinite recursion on return type declared inside body (#GH68775).
+
 Miscellaneous Clang Crashes Fixed
 ^
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

>From 3f1d714a2aa4b236afe9bb1384be073fb155a2b8 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 08:56:56 +0800
Subject: [PATCH 2/3] Limit TypeVisitor checking to 'auto' and lambda
 definition only

1. Fix potential perf regression;
2. Fix comment.
---
 clang/lib/AST/ASTImporter.cpp | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3bbd6ebaf1..d98cb80c349db2 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3647,17 +3647,25 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
 bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = 

[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits


@@ -3647,15 +3647,19 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = dyn_cast(D))
+IsLambdaDefinition = cast(MD->getDeclContext())->isLambda();

danix800 wrote:

Got it! Thanks for these useful info!

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits


@@ -3647,15 +3647,19 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = dyn_cast(D))
+IsLambdaDefinition = cast(MD->getDeclContext())->isLambda();

danix800 wrote:

Or does this mean to test `!FromFPT->hasTrailingReturn()`?

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits


@@ -3647,15 +3647,19 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = dyn_cast(D))
+IsLambdaDefinition = cast(MD->getDeclContext())->isLambda();

danix800 wrote:

> Thanks, this works, but if we are going this way, why not also check the 
> lambda was defined without a return type?

Could you please give some direction on how to test **the lambda was defined 
without a return type**?

Does this mean that we need to check for possible `return` statements within 
lambda?

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

danix800 wrote:

> I think it would be a good idea to double check this for performance 
> regressions, since this case will recurse into the function every time with 
> this patch. Though I don't know if there is a better way to test it than to 
> merge it and wait for it to be picked up by google.

For large TU it's worth considering for performance. The previous commit 
relaxed the `TypeVisitor` checking to all `FunctionDecl`. I reverted back to 
the original `auto` impl, plus an extra condition that if it's a `lambda` 
definition, see 
https://github.com/llvm/llvm-project/pull/89096/commits/3f1d714a2aa4b236afe9bb1384be073fb155a2b8

> 
> Another idea to avoid any potential regressions, is to mark the return type 
> as deduced anyway, with the distinction that 'auto' was not written.

I tested this idea, might be like this:
```
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 712958594473..988efcbef3a3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3680,24 +3680,10 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
-  FromReturnTy = Importer.getFromContext().VoidTy;
-  UsedDifferentProtoType = true;
-}
-FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
-// FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the
-// FunctionDecl that we are importing the FunctionProtoType for.
-// To avoid an infinite recursion when importing, create the FunctionDecl
-// with a simplified function type.
-if (FromEPI.ExceptionSpec.SourceDecl ||
-FromEPI.ExceptionSpec.SourceTemplate ||
-FromEPI.ExceptionSpec.NoexceptExpr) {
-  FunctionProtoType::ExtProtoInfo DefaultEPI;
-  FromEPI = DefaultEPI;
-  UsedDifferentProtoType = true;
-}
+FunctionProtoType::ExtProtoInfo DefaultEPI;
+UsedDifferentProtoType = true;
 FromTy = Importer.getFromContext().getFunctionType(
-FromReturnTy, FromFPT->getParamTypes(), FromEPI);
+Importer.getFromContext().VoidTy, FromFPT->getParamTypes(), 
DefaultEPI);
 FromTSI = Importer.getFromContext().getTrivialTypeSourceInfo(
 FromTy, D->getBeginLoc());
   }
```
but this will break two testcases from `check-clang-astmerge-exprs-cpp`:
```
Failed Tests (2):
  Clang :: ASTMerge/class-template/test.cpp
  Clang :: ASTMerge/exprs-cpp/test.cpp
```

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits


@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.

danix800 wrote:

Thanks for reminding, fixed in 
https://github.com/llvm/llvm-project/pull/89096/commits/3f1d714a2aa4b236afe9bb1384be073fb155a2b8

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0d6d52365a5d31045c347412c3a0fe8be7119006 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:33:29 +0800
Subject: [PATCH 1/2] [ASTImporter] Fix infinite recurse on return type
 declared inside body (#68775)

Lambda without trailing auto could has return type declared
inside the body too.
---
 clang/docs/ReleaseNotes.rst |  2 ++
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c19ad9fba58f37..7a623c6be72fd2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,8 @@ Bug Fixes to AST Handling
 Miscellaneous Bug Fixes
 ^^^
 
+- Fixed an infinite recursion on return type declared inside body (#GH68775).
+
 Miscellaneous Clang Crashes Fixed
 ^
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

>From 3f1d714a2aa4b236afe9bb1384be073fb155a2b8 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 08:56:56 +0800
Subject: [PATCH 2/2] Limit TypeVisitor checking to 'auto' and lambda
 definition only

1. Fix potential perf regression;
2. Fix comment.
---
 clang/lib/AST/ASTImporter.cpp | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3bbd6ebaf1..d98cb80c349db2 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3647,17 +3647,25 @@ class IsTypeDeclaredInsideVisitor
 };
 } // namespace
 
-/// This function checks if the function has 'auto' return type that contains
+/// This function checks if the given function has a return type that contains
 /// a reference (in any way) to a declaration inside the same function.
 bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
+  bool IsLambdaDefinition = false;
+  if (const auto *MD = 

[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0d6d52365a5d31045c347412c3a0fe8be7119006 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:33:29 +0800
Subject: [PATCH] [ASTImporter] Fix infinite recurse on return type declared
 inside body (#68775)

Lambda without trailing auto could has return type declared
inside the body too.
---
 clang/docs/ReleaseNotes.rst |  2 ++
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c19ad9fba58f37..7a623c6be72fd2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,8 @@ Bug Fixes to AST Handling
 Miscellaneous Bug Fixes
 ^^^
 
+- Fixed an infinite recursion on return type declared inside body (#GH68775).
+
 Miscellaneous Clang Crashes Fixed
 ^
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/89096

>From 0f7ddbfef8ca9c93efacfb2a437ddb5645ca07b1 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:03:14 +0800
Subject: [PATCH] [ASTImporter] Fix infinite recurse on return type declared
 inside body (#68775)

Lambda without trailing auto could has return type declared inside the
body too.
---
 .cproject   | 125 
 .project|  27 +
 .settings/language.settings.xml |  27 +
 .settings/org.eclipse.cdt.core.prefs|   6 +
 clang/docs/ReleaseNotes.rst |   2 +
 clang/lib/AST/ASTImporter.cpp   |  16 +--
 clang/unittests/AST/ASTImporterTest.cpp |  16 +++
 expand-modular-headers-ppcallbacks.cpp.diff |  55 +
 8 files changed, 264 insertions(+), 10 deletions(-)
 create mode 100644 .cproject
 create mode 100644 .project
 create mode 100644 .settings/language.settings.xml
 create mode 100644 .settings/org.eclipse.cdt.core.prefs
 create mode 100644 expand-modular-headers-ppcallbacks.cpp.diff

diff --git a/.cproject b/.cproject
new file mode 100644
index 00..36ee502ff51294
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,125 @@
+
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   

+   

+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+

[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

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


[clang] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) (PR #89096)

2024-04-17 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/89096

Lambda without trailing auto could has return type declared inside the body too.

>From 6390eb0618e88c1c176329c6d49a45e16944f248 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Thu, 18 Apr 2024 00:03:14 +0800
Subject: [PATCH] [ASTImporter] Fix infinite recurse on return type declared
 inside body (#68775)

Lambda without trailing auto could has return type declared inside the
body too.
---
 clang/lib/AST/ASTImporter.cpp   | 16 ++--
 clang/unittests/AST/ASTImporterTest.cpp | 16 
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6aaa34c55ce307..3bbd6ebaf1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -695,7 +695,7 @@ namespace clang {
 // Returns true if the given function has a placeholder return type and
 // that type is declared inside the body of the function.
 // E.g. auto f() { struct X{}; return X(); }
-bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+bool hasReturnTypeDeclaredInside(FunctionDecl *D);
   };
 
 template 
@@ -3649,19 +3649,15 @@ class IsTypeDeclaredInsideVisitor
 
 /// This function checks if the function has 'auto' return type that contains
 /// a reference (in any way) to a declaration inside the same function.
-bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
+bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
   QualType FromTy = D->getType();
   const auto *FromFPT = FromTy->getAs();
   assert(FromFPT && "Must be called on FunctionProtoType");
 
   QualType RetT = FromFPT->getReturnType();
-  if (isa(RetT.getTypePtr())) {
-FunctionDecl *Def = D->getDefinition();
-IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
-return Visitor.CheckType(RetT);
-  }
-
-  return false;
+  FunctionDecl *Def = D->getDefinition();
+  IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
+  return Visitor.CheckType(RetT);
 }
 
 ExplicitSpecifier
@@ -3811,7 +3807,7 @@ ExpectedDecl 
ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
 // E.g.: auto foo() { struct X{}; return X(); }
 // To avoid an infinite recursion when importing, create the FunctionDecl
 // with a simplified return type.
-if (hasAutoReturnTypeDeclaredInside(D)) {
+if (hasReturnTypeDeclaredInside(D)) {
   FromReturnTy = Importer.getFromContext().VoidTy;
   UsedDifferentProtoType = true;
 }
diff --git a/clang/unittests/AST/ASTImporterTest.cpp 
b/clang/unittests/AST/ASTImporterTest.cpp
index acc596fef87b76..3fac5514319c24 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6721,6 +6721,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, 
LambdaInFunctionBody) {
   EXPECT_FALSE(FromL->isDependentLambda());
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, LambdaReturnTypeDeclaredInside) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  void foo() {
+(void) []() {
+  struct X {};
+  return X();
+};
+  }
+  )",
+  Lang_CXX11, "", Lang_CXX11, "foo");
+  auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr());
+  EXPECT_TRUE(ToLambda);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
   Decl *FromTU = getTuDecl(
   R"(

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-16 Thread Ding Fei via cfe-commits

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


[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-15 Thread Ding Fei via cfe-commits


@@ -13805,29 +13804,24 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized.
 // This is true even in C++ for OpenCL.
 } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init);

danix800 wrote:

No, this defaults to `diag::err_init_element_not_constant`.

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


[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-15 Thread Ding Fei via cfe-commits


@@ -3391,7 +3391,7 @@ class Sema final : public SemaBase {
   bool ConstexprSupported, bool CLinkageMayDiffer);
 
   /// type checking declaration initializers (C99 6.7.8)
-  bool CheckForConstantInitializer(Expr *e, QualType t);
+  bool CheckForConstantInitializer(Expr *Init, unsigned DiagID);

danix800 wrote:

Thanks for reviewing, I'll add default `DiagID` to 
`diag::err_init_element_not_constant`.

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


[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-15 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/88014

>From 9b293d37ec5c0193e3ad4e1bab2d382ebe54d7b6 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Tue, 9 Apr 2024 00:26:03 +0800
Subject: [PATCH 1/3] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid
 InitListExpr (#88008)

Use refactored CheckForConstantInitializer() to skip checking expr with error.
---
 clang/include/clang/Sema/Sema.h   |  2 +-
 clang/lib/Sema/SemaDecl.cpp   | 28 ---
 clang/lib/Sema/SemaExpr.cpp   |  3 +-
 .../test/Sema/recover-expr-gh88008-nocrash.c  | 11 
 4 files changed, 25 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/Sema/recover-expr-gh88008-nocrash.c

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d93ac7863b721d..79bf44116d0acc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3431,7 +3431,7 @@ class Sema final : public SemaBase {
   bool ConstexprSupported, bool CLinkageMayDiffer);
 
   /// type checking declaration initializers (C99 6.7.8)
-  bool CheckForConstantInitializer(Expr *e, QualType t);
+  bool CheckForConstantInitializer(Expr *Init, unsigned DiagID);
 
   QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
 QualType Type, TypeSourceInfo *TSI,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 8b3b9d020db572..6529e12e107fb7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12668,7 +12668,7 @@ void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) {
   }
 }
 
-bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+bool Sema::CheckForConstantInitializer(Expr *Init, unsigned DiagID) {
   // FIXME: Need strict checking.  In C89, we need to check for
   // any assignment, increment, decrement, function-calls, or
   // commas outside of a sizeof.  In C99, it's the same list,
@@ -12686,8 +12686,7 @@ bool Sema::CheckForConstantInitializer(Expr *Init, 
QualType DclT) {
   const Expr *Culprit;
   if (Init->isConstantInitializer(Context, false, ))
 return false;
-  Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant)
-<< Culprit->getSourceRange();
+  Diag(Culprit->getExprLoc(), DiagID) << Culprit->getSourceRange();
   return true;
 }
 
@@ -13805,29 +13804,24 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized.
 // This is true even in C++ for OpenCL.
 } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
 
-// Otherwise, C++ does not restrict the initializer.
+  // Otherwise, C++ does not restrict the initializer.
 } else if (getLangOpts().CPlusPlus) {
   // do nothing
 
 // C99 6.7.8p4: All the expressions in an initializer for an object that 
has
 // static storage duration shall be constant expressions or string 
literals.
 } else if (VDecl->getStorageClass() == SC_Static) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
 
-// C89 is stricter than C99 for aggregate initializers.
-// C89 6.5.7p3: All the expressions [...] in an initializer list
-// for an object that has aggregate or union type shall be
-// constant expressions.
+  // C89 is stricter than C99 for aggregate initializers.
+  // C89 6.5.7p3: All the expressions [...] in an initializer list
+  // for an object that has aggregate or union type shall be
+  // constant expressions.
 } else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
isa(Init)) {
-  const Expr *Culprit;
-  if (!Init->isConstantInitializer(Context, false, )) {
-Diag(Culprit->getExprLoc(),
- diag::ext_aggregate_init_not_constant)
-  << Culprit->getSourceRange();
-  }
+  CheckForConstantInitializer(Init, diag::ext_aggregate_init_not_constant);
 }
 
 if (auto *E = dyn_cast(Init))
@@ -13960,7 +13954,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // Avoid duplicate diagnostics for constexpr variables.
 if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
 !VDecl->isConstexpr())
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
   }
 
   QualType InitType = Init->getType();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 24f354f1c72498..4b846bb2a1bb43 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7880,7 +7880,8 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, 
TypeSourceInfo 

[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-12 Thread Ding Fei via cfe-commits

danix800 wrote:

ping @Endilll 

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


[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2024-04-09 Thread Ding Fei via cfe-commits

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


[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-08 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/88014

>From fbd0780923d40b0d8290280731239a722a7af7a9 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Tue, 9 Apr 2024 00:26:03 +0800
Subject: [PATCH 1/2] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid
 InitListExpr (#88008)

Use refactored CheckForConstantInitializer() to skip checking expr with error.
---
 clang/include/clang/Sema/Sema.h   |  2 +-
 clang/lib/Sema/SemaDecl.cpp   | 28 ---
 clang/lib/Sema/SemaExpr.cpp   |  3 +-
 .../test/Sema/recover-expr-gh88008-nocrash.c  | 11 
 4 files changed, 25 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/Sema/recover-expr-gh88008-nocrash.c

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 56d66a4486e0e7..452ccdda868b55 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3391,7 +3391,7 @@ class Sema final : public SemaBase {
   bool ConstexprSupported, bool CLinkageMayDiffer);
 
   /// type checking declaration initializers (C99 6.7.8)
-  bool CheckForConstantInitializer(Expr *e, QualType t);
+  bool CheckForConstantInitializer(Expr *Init, unsigned DiagID);
 
   QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
 QualType Type, TypeSourceInfo *TSI,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c790dab72dd721..a516cff166fd67 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12769,7 +12769,7 @@ void Sema::DiagnoseHLSLAttrStageMismatch(
   << (AllowedStages.size() != 1) << join(StageStrings, ", ");
 }
 
-bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+bool Sema::CheckForConstantInitializer(Expr *Init, unsigned DiagID) {
   // FIXME: Need strict checking.  In C89, we need to check for
   // any assignment, increment, decrement, function-calls, or
   // commas outside of a sizeof.  In C99, it's the same list,
@@ -12787,8 +12787,7 @@ bool Sema::CheckForConstantInitializer(Expr *Init, 
QualType DclT) {
   const Expr *Culprit;
   if (Init->isConstantInitializer(Context, false, ))
 return false;
-  Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant)
-<< Culprit->getSourceRange();
+  Diag(Culprit->getExprLoc(), DiagID) << Culprit->getSourceRange();
   return true;
 }
 
@@ -13906,29 +13905,24 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized.
 // This is true even in C++ for OpenCL.
 } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
 
-// Otherwise, C++ does not restrict the initializer.
+  // Otherwise, C++ does not restrict the initializer.
 } else if (getLangOpts().CPlusPlus) {
   // do nothing
 
 // C99 6.7.8p4: All the expressions in an initializer for an object that 
has
 // static storage duration shall be constant expressions or string 
literals.
 } else if (VDecl->getStorageClass() == SC_Static) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
 
-// C89 is stricter than C99 for aggregate initializers.
-// C89 6.5.7p3: All the expressions [...] in an initializer list
-// for an object that has aggregate or union type shall be
-// constant expressions.
+  // C89 is stricter than C99 for aggregate initializers.
+  // C89 6.5.7p3: All the expressions [...] in an initializer list
+  // for an object that has aggregate or union type shall be
+  // constant expressions.
 } else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
isa(Init)) {
-  const Expr *Culprit;
-  if (!Init->isConstantInitializer(Context, false, )) {
-Diag(Culprit->getExprLoc(),
- diag::ext_aggregate_init_not_constant)
-  << Culprit->getSourceRange();
-  }
+  CheckForConstantInitializer(Init, diag::ext_aggregate_init_not_constant);
 }
 
 if (auto *E = dyn_cast(Init))
@@ -14061,7 +14055,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // Avoid duplicate diagnostics for constexpr variables.
 if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
 !VDecl->isConstexpr())
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
   }
 
   QualType InitType = Init->getType();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8db4fffeecfe35..2016d2eb08e0ff 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7898,7 +7898,8 @@ 

[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2024-04-08 Thread Ding Fei via cfe-commits

danix800 wrote:

> LGTM but please add a release note so users know about the bug fix.

Release note added.

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


[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2024-04-08 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/76619

>From 0ca1a2b2573d1f89a1b4d13cd43628a46c1e5c98 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Sun, 31 Dec 2023 00:32:01 +0800
Subject: [PATCH] [ASTMatchers] fix captureVars assertion failure on
 capturesVariables

Matcher 'capturesVar' should check for capturesVariables() before
calling getCaptureVar() since it asserts this LambdaCapture does capture
a variable.

Fixes #76425
---
 clang/docs/ReleaseNotes.rst | 1 +
 clang/include/clang/ASTMatchers/ASTMatchers.h   | 2 ++
 clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 2 ++
 3 files changed, 5 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index abf15c8dc49d9e..8d9ccf789d9cb8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -633,6 +633,7 @@ AST Matchers
 - Add ``isExplicitObjectMemberFunction``.
 - Fixed ``forEachArgumentWithParam`` and ``forEachArgumentWithParamType`` to
   not skip the explicit object parameter for operator calls.
+- Fixed captureVars assertion failure if not capturesVariables. (#GH76425)
 
 clang-format
 
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..8a2bbfff9e9e6b 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4961,6 +4961,8 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, 
internal::Matcher,
 /// capturesVar(hasName("x")) matches `x` and `x = 1`.
 AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher,
   InnerMatcher) {
+  if (!Node.capturesVariable())
+return false;
   auto *capturedVar = Node.getCapturedVar();
   return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
 }
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp 
b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 0edc65162fbe3f..b76627cb9be637 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2321,6 +2321,8 @@ TEST_P(ASTMatchersTest, 
LambdaCaptureTest_BindsToCaptureOfVarDecl) {
   matches("int main() { int cc; auto f = [=](){ return cc; }; }", 
matcher));
   EXPECT_TRUE(
   matches("int main() { int cc; auto f = [&](){ return cc; }; }", 
matcher));
+  EXPECT_TRUE(matches(
+  "void f(int a) { int cc[a]; auto f = [&](){ return cc;}; }", matcher));
 }
 
 TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (PR #88014)

2024-04-08 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/88014

Use refactored `CheckForConstantInitializer()` to skip checking expr with error.

>From fbd0780923d40b0d8290280731239a722a7af7a9 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Tue, 9 Apr 2024 00:26:03 +0800
Subject: [PATCH] [AST][RecoveryExpr] Fix a crash on c89/c90 invalid
 InitListExpr (#88008)

Use refactored CheckForConstantInitializer() to skip checking expr with error.
---
 clang/include/clang/Sema/Sema.h   |  2 +-
 clang/lib/Sema/SemaDecl.cpp   | 28 ---
 clang/lib/Sema/SemaExpr.cpp   |  3 +-
 .../test/Sema/recover-expr-gh88008-nocrash.c  | 11 
 4 files changed, 25 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/Sema/recover-expr-gh88008-nocrash.c

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 56d66a4486e0e7..452ccdda868b55 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3391,7 +3391,7 @@ class Sema final : public SemaBase {
   bool ConstexprSupported, bool CLinkageMayDiffer);
 
   /// type checking declaration initializers (C99 6.7.8)
-  bool CheckForConstantInitializer(Expr *e, QualType t);
+  bool CheckForConstantInitializer(Expr *Init, unsigned DiagID);
 
   QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
 QualType Type, TypeSourceInfo *TSI,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c790dab72dd721..a516cff166fd67 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12769,7 +12769,7 @@ void Sema::DiagnoseHLSLAttrStageMismatch(
   << (AllowedStages.size() != 1) << join(StageStrings, ", ");
 }
 
-bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+bool Sema::CheckForConstantInitializer(Expr *Init, unsigned DiagID) {
   // FIXME: Need strict checking.  In C89, we need to check for
   // any assignment, increment, decrement, function-calls, or
   // commas outside of a sizeof.  In C99, it's the same list,
@@ -12787,8 +12787,7 @@ bool Sema::CheckForConstantInitializer(Expr *Init, 
QualType DclT) {
   const Expr *Culprit;
   if (Init->isConstantInitializer(Context, false, ))
 return false;
-  Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant)
-<< Culprit->getSourceRange();
+  Diag(Culprit->getExprLoc(), DiagID) << Culprit->getSourceRange();
   return true;
 }
 
@@ -13906,29 +13905,24 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized.
 // This is true even in C++ for OpenCL.
 } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
 
-// Otherwise, C++ does not restrict the initializer.
+  // Otherwise, C++ does not restrict the initializer.
 } else if (getLangOpts().CPlusPlus) {
   // do nothing
 
 // C99 6.7.8p4: All the expressions in an initializer for an object that 
has
 // static storage duration shall be constant expressions or string 
literals.
 } else if (VDecl->getStorageClass() == SC_Static) {
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
 
-// C89 is stricter than C99 for aggregate initializers.
-// C89 6.5.7p3: All the expressions [...] in an initializer list
-// for an object that has aggregate or union type shall be
-// constant expressions.
+  // C89 is stricter than C99 for aggregate initializers.
+  // C89 6.5.7p3: All the expressions [...] in an initializer list
+  // for an object that has aggregate or union type shall be
+  // constant expressions.
 } else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
isa(Init)) {
-  const Expr *Culprit;
-  if (!Init->isConstantInitializer(Context, false, )) {
-Diag(Culprit->getExprLoc(),
- diag::ext_aggregate_init_not_constant)
-  << Culprit->getSourceRange();
-  }
+  CheckForConstantInitializer(Init, diag::ext_aggregate_init_not_constant);
 }
 
 if (auto *E = dyn_cast(Init))
@@ -14061,7 +14055,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 // Avoid duplicate diagnostics for constexpr variables.
 if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
 !VDecl->isConstexpr())
-  CheckForConstantInitializer(Init, DclT);
+  CheckForConstantInitializer(Init, diag::err_init_element_not_constant);
   }
 
   QualType InitType = Init->getType();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8db4fffeecfe35..2016d2eb08e0ff 100644
--- a/clang/lib/Sema/SemaExpr.cpp

[clang] [clang][ASTImporter] fix assert fail due to offset overflow (PR #79084)

2024-01-29 Thread Ding Fei via cfe-commits


@@ -9896,9 +9903,13 @@ Expected ASTImporter::Import(FileID FromID, bool 
IsBuiltin) {
 // FIXME: The filename may be a virtual name that does probably not
 // point to a valid file and we get no Entry here. In this case try 
with
 // the memory buffer below.

danix800 wrote:

Invalid file could exist in real case (causes no Entry) while `SourceLocation` 
overflow is normally caused by cumulative effect of multiple (large enough) 
files imported so I think these two are not connected.

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


[clang] [clang][ASTImporter] fix assert fail due to offset overflow (PR #79084)

2024-01-29 Thread Ding Fei via cfe-commits


@@ -9896,9 +9903,13 @@ Expected ASTImporter::Import(FileID FromID, bool 
IsBuiltin) {
 // FIXME: The filename may be a virtual name that does probably not
 // point to a valid file and we get no Entry here. In this case try 
with
 // the memory buffer below.
-if (Entry)
+if (Entry) {
+  if (isBufferSizeOverflow(ToSM, Entry->getSize()))
+return llvm::make_error(
+ASTImportError::UnsupportedConstruct);

danix800 wrote:

`ASTImportError::Unknown` would crash CTU module too, 
`ASTImportError::UnsupportedConstruct` might be deliberately chosen so the 
analysis could continue in this case.

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


[clang] [clang][Parser] Pop scope prior VarDecl invalidating by invalid init (PR #77434)

2024-01-09 Thread Ding Fei via cfe-commits

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


[clang] [clang][Parser] Pop scope prior VarDecl invalidating by invalid init (PR #77434)

2024-01-09 Thread Ding Fei via cfe-commits

danix800 wrote:

> This makes sense to me but I would like @cor3ntin to review as well.
> 
> This needs a release note.

Release note is added.

> 
> I see that there was two test cases. Do you think it is worth it to add the 
> second test case as well?

The original testcase from #30908 is added too for completeness.

Please take another look @shafik @cor3ntin 

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


[clang] [clang][Parser] Pop scope prior VarDecl invalidating by invalid init (PR #77434)

2024-01-09 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/77434

>From 2f9e45458d21952f9e81cd54297f538d1d04b9f9 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Tue, 9 Jan 2024 16:40:23 +0800
Subject: [PATCH] [clang][Parser] Pop scope prior VarDecl invalidating by
 invalid direct Init

Invalid (direct) initializer would invalid VarDecl so InitializerScopeRAII
cannot restore scope stack balance.

As with other kind of initializers, InitializerScopeRAII::pop() is moved up
before Sema::ActOnInitializerError() which invalidates the VarDecl, so
scope can be balanced and current DeclContext can be restored.

Fixes #30908
---
 clang/docs/ReleaseNotes.rst   |  3 +++
 clang/lib/Parse/ParseDecl.cpp |  8 +--
 ...e-balance-on-invalid-var-direct-init-1.cpp | 20 +
 ...e-balance-on-invalid-var-direct-init-2.cpp | 22 +++
 4 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 
clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp
 create mode 100644 
clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ddeb1186d65ac8..46f4b82b89e488 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -702,6 +702,9 @@ Bug Fixes in This Version
 - Fix assertion failure when initializing union containing struct with
   flexible array member using empty initializer list.
   Fixes (`#77085 `_)
+- Fix assertion crash due to failed scope restoring caused by too-early VarDecl
+  invalidation by invalid initializer Expr.
+  Fixes (`#30908 `_)
 
 
 Bug Fixes to Compiler Builtins
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index b60ae293ef8c20..ed684c5d57b1ee 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2661,7 +2661,12 @@ Decl 
*Parser::ParseDeclarationAfterDeclaratorAndAttributes(
   // ProduceConstructorSignatureHelp only on VarDecls.
   ExpressionStarts = SetPreferredType;
 }
-if (ParseExpressionList(Exprs, ExpressionStarts)) {
+
+bool SawError = ParseExpressionList(Exprs, ExpressionStarts);
+
+InitScope.pop();
+
+if (SawError) {
   if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) 
{
 Actions.ProduceConstructorSignatureHelp(
 ThisVarDecl->getType()->getCanonicalTypeInternal(),
@@ -2674,7 +2679,6 @@ Decl 
*Parser::ParseDeclarationAfterDeclaratorAndAttributes(
 } else {
   // Match the ')'.
   T.consumeClose();
-  InitScope.pop();
 
   ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
   T.getCloseLocation(),
diff --git 
a/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp 
b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp
new file mode 100644
index 00..1a692fe8ff1e72
--- /dev/null
+++ b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -ferror-limit 2 -fsyntax-only -verify %s
+
+// expected-error@* {{too many errors emitted}}
+
+namespace llvm {
+namespace Hexagon {}
+}
+void set() {
+  Hexagon::NoRegister;
+  // expected-error@-1 {{use of undeclared identifier}}
+  // expected-note@-5 {{declared here}}
+  // expected-error@-3 {{no member named 'NoRegister' in namespace}}
+}
+template  struct pair { pair(int, int); };
+struct HexagonMCChecker {
+  static pair Unconditional;
+  void checkRegisters();
+};
+pair HexagonMCChecker::Unconditional(Hexagon::NoRegister, 0);
+void HexagonMCChecker::checkRegisters() {}
diff --git 
a/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp 
b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp
new file mode 100644
index 00..02200ce4f34a75
--- /dev/null
+++ b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include  // expected-error {{file not found}}
+
+class S {};
+
+template 
+class E {
+public:
+  E(S* scope) {}
+  S ();
+};
+
+class Z {
+ private:
+  static E e;
+  static S& s();
+};
+
+E Z::e(&__UNKNOWN_ID__);
+
+S& Z::s() { return Z::e.getS(); }

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2024-01-09 Thread Ding Fei via cfe-commits

danix800 wrote:

> Thank you for the fix, can you add more details to your summary. The summary 
> is what usually goes into the git log. We would like those to be as 
> descriptive as possible to avoid having to do extra digging to understand the 
> change at a high level.

Thanks for reminding. Summary updated, please take another look.

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


[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2024-01-09 Thread Ding Fei via cfe-commits

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


[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2024-01-09 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/76619

>From 50c0ccd9a28896a1f8f673446054abd6f18703a9 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Sun, 31 Dec 2023 00:32:01 +0800
Subject: [PATCH] [ASTMatchers] fix captureVars assertion failure on
 capturesVariables

Matcher 'capturesVar' should check for capturesVariables() before
calling getCaptureVar() since it asserts this LambdaCapture does capture
a variable.

Fixes #76425
---
 clang/include/clang/ASTMatchers/ASTMatchers.h   | 2 ++
 clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 82a26356c58f556..91c33e4b1163e6d 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4817,6 +4817,8 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, 
internal::Matcher,
 /// capturesVar(hasName("x")) matches `x` and `x = 1`.
 AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher,
   InnerMatcher) {
+  if (!Node.capturesVariable())
+return false;
   auto *capturedVar = Node.getCapturedVar();
   return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
 }
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp 
b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 8f0dd5602307c53..eb493f9c3050acb 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2308,6 +2308,8 @@ TEST_P(ASTMatchersTest, 
LambdaCaptureTest_BindsToCaptureOfVarDecl) {
   matches("int main() { int cc; auto f = [=](){ return cc; }; }", 
matcher));
   EXPECT_TRUE(
   matches("int main() { int cc; auto f = [&](){ return cc; }; }", 
matcher));
+  EXPECT_TRUE(matches(
+  "void f(int a) { int cc[a]; auto f = [&](){ return cc;}; }", matcher));
 }
 
 TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Parser] Pop scope prior VarDecl invalidating by invalid init (PR #77434)

2024-01-09 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/77434

Invalid (direct) initializer would invalid `VarDecl` so `InitializerScopeRAII` 
cannot restore scope stack balance.

As with other kind of initializer, `InitializerScopeRAII::pop()` is moved up 
before `Sema::ActOnInitializerError()` which invalidates the `VarDecl`, so 
scope can be balanced and current `DeclContext` can be restored.

Fixes #30908

>From 6934d23d9276a0a0997a31d206ffaaa146243db1 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Tue, 9 Jan 2024 16:40:23 +0800
Subject: [PATCH] [clang][Parser] Pop scope prior VarDecl invalidating by
 invalid direct Init

Invalid (direct) initializer would invalid VarDecl so InitializerScopeRAII
cannot restore scope stack balance.

As with other kind of initializer, InitializerScopeRAII::pop() is moved up
before Sema::ActOnInitializerError() which invalidates the VarDecl, so
scope can be balanced and current DeclContext can be restored.

Fixes #30908
---
 clang/lib/Parse/ParseDecl.cpp |  8 +--
 ...ope-balance-on-invalid-var-direct-init.cpp | 22 +++
 2 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 
clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init.cpp

diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index b60ae293ef8c20..ed684c5d57b1ee 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2661,7 +2661,12 @@ Decl 
*Parser::ParseDeclarationAfterDeclaratorAndAttributes(
   // ProduceConstructorSignatureHelp only on VarDecls.
   ExpressionStarts = SetPreferredType;
 }
-if (ParseExpressionList(Exprs, ExpressionStarts)) {
+
+bool SawError = ParseExpressionList(Exprs, ExpressionStarts);
+
+InitScope.pop();
+
+if (SawError) {
   if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) 
{
 Actions.ProduceConstructorSignatureHelp(
 ThisVarDecl->getType()->getCanonicalTypeInternal(),
@@ -2674,7 +2679,6 @@ Decl 
*Parser::ParseDeclarationAfterDeclaratorAndAttributes(
 } else {
   // Match the ')'.
   T.consumeClose();
-  InitScope.pop();
 
   ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
   T.getCloseLocation(),
diff --git 
a/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init.cpp 
b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init.cpp
new file mode 100644
index 00..02200ce4f34a75
--- /dev/null
+++ b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include  // expected-error {{file not found}}
+
+class S {};
+
+template 
+class E {
+public:
+  E(S* scope) {}
+  S ();
+};
+
+class Z {
+ private:
+  static E e;
+  static S& s();
+};
+
+E Z::e(&__UNKNOWN_ID__);
+
+S& Z::s() { return Z::e.getS(); }

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ASTMatchers] fix captureVars assertion failure on capturesVariables (PR #76619)

2023-12-30 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/76619

Fixes #76425

>From b26fa2acfd4974d1c09eef408b4d6c2dcbb16479 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Sun, 31 Dec 2023 00:32:01 +0800
Subject: [PATCH] [ASTMatchers] fix captureVars assertion failure on
 capturesVariables

Fixes #76425
---
 clang/include/clang/ASTMatchers/ASTMatchers.h   | 2 ++
 clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 82a26356c58f55..91c33e4b1163e6 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4817,6 +4817,8 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, 
internal::Matcher,
 /// capturesVar(hasName("x")) matches `x` and `x = 1`.
 AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher,
   InnerMatcher) {
+  if (!Node.capturesVariable())
+return false;
   auto *capturedVar = Node.getCapturedVar();
   return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
 }
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp 
b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 8f0dd5602307c5..eb493f9c3050ac 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2308,6 +2308,8 @@ TEST_P(ASTMatchersTest, 
LambdaCaptureTest_BindsToCaptureOfVarDecl) {
   matches("int main() { int cc; auto f = [=](){ return cc; }; }", 
matcher));
   EXPECT_TRUE(
   matches("int main() { int cc; auto f = [&](){ return cc; }; }", 
matcher));
+  EXPECT_TRUE(matches(
+  "void f(int a) { int cc[a]; auto f = [&](){ return cc;}; }", matcher));
 }
 
 TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][ASTImporter] Fix crash when template class static member imported to other translation unit. (PR #68774)

2023-10-12 Thread Ding Fei via cfe-commits

danix800 wrote:

Caused by missing `MemberSpecializationInfo` when importing so moving testcase 
into `ASTImporterTest` as unittest would be better.

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


[clang] [StructuralEquivalence] fix crash & improve comparing on GenericSelectionExpr (PR #67458)

2023-09-26 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/67458

>From 9bf05ae5cd69fb99e1978cdc766f8392f92626c3 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 27 Sep 2023 01:01:06 +0800
Subject: [PATCH] [StructuralEquivalence] fix crash & improve comparing on
 GenericSelectionExpr

1. fix crash on 'default' assoc which has no TypeSourceInfo (nullptr);
2. improve equivalency comparison on control expr & associated exprs.
---
 clang/lib/AST/ASTStructuralEquivalence.cpp| 20 +
 .../AST/StructuralEquivalenceTest.cpp | 22 +++
 2 files changed, 42 insertions(+)

diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp 
b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 5b98d14dd3d9104..d9b2f045552d52c 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -247,6 +247,20 @@ class StmtComparer {
 
   bool IsStmtEquivalent(const GenericSelectionExpr *E1,
 const GenericSelectionExpr *E2) {
+if (!IsStructurallyEquivalent(Context,
+  const_cast(E1->getControllingExpr()),
+  const_cast(E2->getControllingExpr(
+  return false;
+
+for (auto Pair : zip_longest(E1->getAssocExprs(), E2->getAssocExprs())) {
+  std::optional Child1 = std::get<0>(Pair);
+  std::optional Child2 = std::get<1>(Pair);
+  if (!Child1 || !Child2)
+return false;
+  if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
+return false;
+}
+
 for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
  E2->getAssocTypeSourceInfos())) {
   std::optional Child1 = std::get<0>(Pair);
@@ -255,6 +269,12 @@ class StmtComparer {
   if (!Child1 || !Child2)
 return false;
 
+  if (!(*Child1) != !(*Child2))
+return false;
+
+  if (!(*Child1))
+continue;
+
   if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
 (*Child2)->getType()))
 return false;
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp 
b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 44d950cfe758f14..639cefbc0e99a18 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -2091,6 +2091,28 @@ TEST_F(StructuralEquivalenceStmtTest, 
GenericSelectionExprOrderDiffers) {
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprControlDiffers) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
+"_Generic(1u, unsigned int: 0, float: 1)", 
Lang_C99,
+genericSelectionExpr());
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprAssocExprDiffers) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
+"_Generic(0u, unsigned int: 1u, float: 1)",
+Lang_C99, genericSelectionExpr());
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest,
+   GenericSelectionExprDefaultNoTypeSourceInfo) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, default: 1)",
+"_Generic(0u, unsigned int: 0, default: 1)",
+Lang_C99, genericSelectionExpr());
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) 
{
   auto t = makeStmts(
   R"(

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [StructuralEquivalence] fix crash & improve comparing on GenericSelectionExpr (PR #67458)

2023-09-26 Thread Ding Fei via cfe-commits

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


[clang] fix crash & improve comparing on GenericSelectionExpr (PR #67458)

2023-09-26 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/67458

>From 35bdb04db16c79d68dbe6522d01a0a08b2840d69 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 27 Sep 2023 01:01:06 +0800
Subject: [PATCH] [StructuralEquivalence] fix crash & improve comparing on
 GenericSelectionExpr

1. fix crash on 'default' assoc which has no TypeSourceInfo (nullptr);
2. improve equivalency comparison on control expr & associated exprs.
---
 clang/lib/AST/ASTStructuralEquivalence.cpp| 20 +
 .../AST/StructuralEquivalenceTest.cpp | 22 +++
 2 files changed, 42 insertions(+)

diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp 
b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 5b98d14dd3d9104..d9b2f045552d52c 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -247,6 +247,20 @@ class StmtComparer {
 
   bool IsStmtEquivalent(const GenericSelectionExpr *E1,
 const GenericSelectionExpr *E2) {
+if (!IsStructurallyEquivalent(Context,
+  const_cast(E1->getControllingExpr()),
+  const_cast(E2->getControllingExpr(
+  return false;
+
+for (auto Pair : zip_longest(E1->getAssocExprs(), E2->getAssocExprs())) {
+  std::optional Child1 = std::get<0>(Pair);
+  std::optional Child2 = std::get<1>(Pair);
+  if (!Child1 || !Child2)
+return false;
+  if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
+return false;
+}
+
 for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
  E2->getAssocTypeSourceInfos())) {
   std::optional Child1 = std::get<0>(Pair);
@@ -255,6 +269,12 @@ class StmtComparer {
   if (!Child1 || !Child2)
 return false;
 
+  if (!(*Child1) != !(*Child2))
+return false;
+
+  if (!(*Child1))
+continue;
+
   if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
 (*Child2)->getType()))
 return false;
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp 
b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 44d950cfe758f14..35c1385e73fb389 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -2091,6 +2091,28 @@ TEST_F(StructuralEquivalenceStmtTest, 
GenericSelectionExprOrderDiffers) {
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprControlDiffers) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
+"_Generic(1u, unsigned int: 0, float: 1)", 
Lang_C99,
+genericSelectionExpr());
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprAssocExprDiffers) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
+"_Generic(0u, unsigned int: 1u, float: 1)", 
Lang_C99,
+genericSelectionExpr());
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest,
+   GenericSelectionExprDefaultNoTypeSourceInfo) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, default: 1)",
+"_Generic(0u, unsigned int: 0, default: 1)",
+Lang_C99, genericSelectionExpr());
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) 
{
   auto t = makeStmts(
   R"(

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] fix crash & improve comparing on GenericSelectionExpr (PR #67458)

2023-09-26 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/67458

1. fix crash on 'default' assoc which has no TypeSourceInfo (nullptr);
2. improve equivalency comparison on control expr & associated exprs.

>From e411aa494c09a8f412ee90f302504cd469ef1283 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 27 Sep 2023 01:01:06 +0800
Subject: [PATCH] fix crash & improve comparing on GenericSelectionExpr

1. fix crash on 'default' assoc which has no TypeSourceInfo (nullptr);
2. improve equivalency comparison on control expr & associated exprs.
---
 clang/lib/AST/ASTStructuralEquivalence.cpp| 20 +
 .../AST/StructuralEquivalenceTest.cpp | 22 +++
 2 files changed, 42 insertions(+)

diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp 
b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 5b98d14dd3d9104..d9b2f045552d52c 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -247,6 +247,20 @@ class StmtComparer {
 
   bool IsStmtEquivalent(const GenericSelectionExpr *E1,
 const GenericSelectionExpr *E2) {
+if (!IsStructurallyEquivalent(Context,
+  const_cast(E1->getControllingExpr()),
+  const_cast(E2->getControllingExpr(
+  return false;
+
+for (auto Pair : zip_longest(E1->getAssocExprs(), E2->getAssocExprs())) {
+  std::optional Child1 = std::get<0>(Pair);
+  std::optional Child2 = std::get<1>(Pair);
+  if (!Child1 || !Child2)
+return false;
+  if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
+return false;
+}
+
 for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
  E2->getAssocTypeSourceInfos())) {
   std::optional Child1 = std::get<0>(Pair);
@@ -255,6 +269,12 @@ class StmtComparer {
   if (!Child1 || !Child2)
 return false;
 
+  if (!(*Child1) != !(*Child2))
+return false;
+
+  if (!(*Child1))
+continue;
+
   if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
 (*Child2)->getType()))
 return false;
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp 
b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 44d950cfe758f14..35c1385e73fb389 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -2091,6 +2091,28 @@ TEST_F(StructuralEquivalenceStmtTest, 
GenericSelectionExprOrderDiffers) {
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprControlDiffers) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
+"_Generic(1u, unsigned int: 0, float: 1)", 
Lang_C99,
+genericSelectionExpr());
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprAssocExprDiffers) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
+"_Generic(0u, unsigned int: 1u, float: 1)", 
Lang_C99,
+genericSelectionExpr());
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest,
+   GenericSelectionExprDefaultNoTypeSourceInfo) {
+  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, default: 1)",
+"_Generic(0u, unsigned int: 0, default: 1)",
+Lang_C99, genericSelectionExpr());
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) 
{
   auto t = makeStmts(
   R"(

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Improve constraint inferring on concrete div/mod (PR #65448)

2023-09-15 Thread Ding Fei via cfe-commits

danix800 wrote:

> Uh, this isn't my expertiese. I'm a bit scared to do this alone. I'm also 
> short on time to verify this patch at scale.

Look forward to hear more advice! @llvm/pr-subscribers-clang-static-analyzer 

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


[clang] [analyzer] Improve constraint inferring on concrete div/mod (PR #65448)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -1824,6 +1835,94 @@ RangeSet 
SymbolicRangeInferrer::VisitBinaryOperator(Range LHS,
   return {RangeFactory, ValueFactory.getValue(Min), 
ValueFactory.getValue(Max)};
 }
 
+RangeSet SymbolicRangeInferrer::handleConcreteModulo(Range LHS,
+ llvm::APSInt Modulo,
+ QualType T) {
+  APSIntType ResultType = ValueFactory.getAPSIntType(T);
+  llvm::APSInt Zero = ResultType.getZeroValue();
+  llvm::APSInt One = ResultType.getValue(1);
+
+  if (Modulo == Zero)
+return RangeFactory.getEmptySet();
+  if (Modulo < 0)
+Modulo = -Modulo;
+
+  auto ComputeModuloN = [&](llvm::APSInt From, llvm::APSInt To,
+llvm::APSInt N) -> RangeSet {
+assert(N > Zero && "Non-positive N!");
+bool NonNegative = From >= Zero;
+assert(NonNegative == (To >= Zero) && "Signedness mismatch!");
+
+if (From > To)
+  return RangeFactory.getEmptySet();
+
+llvm::APSInt N1 = N - One;

danix800 wrote:

This is a problem if N is INT_MIN like value, fixed with quick return on such 
values.

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


[clang] [analyzer] Improve constraint inferring on concrete div/mod (PR #65448)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -1824,6 +1835,94 @@ RangeSet 
SymbolicRangeInferrer::VisitBinaryOperator(Range LHS,
   return {RangeFactory, ValueFactory.getValue(Min), 
ValueFactory.getValue(Max)};
 }
 
+RangeSet SymbolicRangeInferrer::handleConcreteModulo(Range LHS,
+ llvm::APSInt Modulo,
+ QualType T) {
+  APSIntType ResultType = ValueFactory.getAPSIntType(T);
+  llvm::APSInt Zero = ResultType.getZeroValue();
+  llvm::APSInt One = ResultType.getValue(1);
+
+  if (Modulo == Zero)
+return RangeFactory.getEmptySet();
+  if (Modulo < 0)
+Modulo = -Modulo;

danix800 wrote:

Actually `X % Y == X % -Y`, not `X % Y == -X % Y` or `X % Y == -X % -Y`. Sign 
of Y is not significant.

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


[clang] [analyzer] Improve constraint inferring on concrete div/mod (PR #65448)

2023-09-15 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-15 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-15 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/65448

>From 111de0e99482cf8c8c206286bb9a4f40149992c6 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH] [analyzer] Improve constraint inferring on concrete div/mod

1. Reduce constraint on modulo with small concrete range when assigned;
2. Improve constraint inferring on modulo over concrete value;
3. Improve constraint inferring on division over concrete value.

Fixes #54377
---
 .../Core/RangeConstraintManager.cpp   | 157 ++
 clang/test/Analysis/constraint-assignor.c | 108 
 clang/test/Analysis/constraint-infer-div.c|  64 +++
 clang/test/Analysis/constraint-infer-mod.c|  98 +++
 4 files changed, 427 insertions(+)
 create mode 100644 clang/test/Analysis/constraint-infer-div.c
 create mode 100644 clang/test/Analysis/constraint-infer-mod.c

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..15f5246335d9d26 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1338,6 +1338,9 @@ class SymbolicRangeInferrer
   RangeSet VisitBinaryOperator(RangeSet LHS, BinaryOperator::Opcode Op,
RangeSet RHS, QualType T);
 
+  RangeSet handleConcreteModulo(Range LHS, llvm::APSInt Modulo, QualType T);
+  RangeSet handleRangeModulo(Range LHS, Range RHS, QualType T);
+
   
//===--===//
   // Ranges and operators
   
//===--===//
@@ -1771,6 +1774,14 @@ template <>
 RangeSet SymbolicRangeInferrer::VisitBinaryOperator(Range LHS,
 Range RHS,
 QualType T) {
+  if (const llvm::APSInt *ModOrNull = RHS.getConcreteValue())
+return handleConcreteModulo(LHS, *ModOrNull, T);
+
+  return handleRangeModulo(LHS, RHS, T);
+}
+
+RangeSet SymbolicRangeInferrer::handleRangeModulo(Range LHS, Range RHS,
+  QualType T) {
   llvm::APSInt Zero = ValueFactory.getAPSIntType(T).getZeroValue();
 
   Range ConservativeRange = getSymmetricalRange(RHS, T);
@@ -1824,6 +1835,101 @@ RangeSet 
SymbolicRangeInferrer::VisitBinaryOperator(Range LHS,
   return {RangeFactory, ValueFactory.getValue(Min), 
ValueFactory.getValue(Max)};
 }
 
+RangeSet SymbolicRangeInferrer::handleConcreteModulo(Range LHS,
+ llvm::APSInt Modulo,
+ QualType T) {
+  APSIntType ResultType = ValueFactory.getAPSIntType(T);
+  llvm::APSInt Zero = ResultType.getZeroValue();
+  llvm::APSInt One = ResultType.getValue(1);
+
+  if (Modulo == Zero)
+return RangeFactory.getEmptySet();
+
+  // Quick path, this also avoids unary '-' overflow on MinValue modulo.
+  if (Modulo == ValueFactory.getMinValue(T) ||
+  Modulo == ValueFactory.getMaxValue(T))
+return RangeFactory.getRangeSet(LHS);
+
+  // Normalize to positive modulo since a % N == a % -N
+  if (Modulo < 0)
+Modulo = -Modulo;
+
+  auto ComputeModuloN = [&](llvm::APSInt From, llvm::APSInt To,
+llvm::APSInt N) -> RangeSet {
+assert(N > Zero && "Positive N expected!");
+bool NonNegative = From >= Zero;
+assert(NonNegative == (To >= Zero) && "Signedness mismatch!");
+
+if (From > To)
+  return RangeFactory.getEmptySet();
+
+llvm::APSInt N1 = N - One;
+
+// spans [0, N - 1] if NonNegative or [-(N - 1), 0] otherwise.
+if ((To - From) / N > Zero)
+  return {RangeFactory, ValueFactory.getValue(NonNegative ? Zero : -N1),
+  ValueFactory.getValue(NonNegative ? N1 : Zero)};
+
+llvm::APSInt Min = From % N;
+llvm::APSInt Max = To % N;
+
+if (Min < Max) // [Min, Max]
+  return {RangeFactory, ValueFactory.getValue(Min),
+  ValueFactory.getValue(Max)};
+
+// [0, Max] U [Min, N - 1] if NonNegative, or
+// [-(N - 1), Max] U [Min, 0] otherwise.
+const llvm::APSInt  = ValueFactory.getValue(NonNegative ? Zero : -N1);
+const llvm::APSInt  = ValueFactory.getValue(Max);
+RangeSet RS1{RangeFactory, Min1, Max1};
+
+const llvm::APSInt  = ValueFactory.getValue(Min);
+const llvm::APSInt  = ValueFactory.getValue(NonNegative ? N1 : Zero);
+RangeSet RS2{RangeFactory, Min2, Max2};
+
+return RangeFactory.unite(RS1, RS2);
+  };
+
+  if (!LHS.Includes(Zero))
+return ComputeModuloN(LHS.From(), LHS.To(), Modulo);
+
+  // split over [From, -1] U [0, To] for easy handling.
+  return RangeFactory.unite(ComputeModuloN(LHS.From(), -One, Modulo),
+ComputeModuloN(Zero, LHS.To(), 

[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits

danix800 wrote:

`auto-merge` might be disabled probably. I can't find the button mentioned 
[here](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request).

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


[clang] [clang][AST] fix lack comparison of declRefExpr in ASTStructuralEquivalence (PR #66041)

2023-09-15 Thread Ding Fei via cfe-commits

danix800 wrote:

LGTM! If no further comment I'll merge this in a day or two.

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


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66498)

2023-09-15 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits

danix800 wrote:

Fixed and resubmited #66498

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


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66498)

2023-09-15 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/66498

NonLoc symbolic SVal to Loc casts are not supported except for 
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can go through 
nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
long long t2 = t1 + 3;
if (!t2) {
  int *p = (int *) t2;
  clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
}
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p' is unknown.

Fixes #62232

>From 0b776deb2bbd4d03325b02680eb99c788d3bc37d Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Fri, 15 Sep 2023 14:01:26 +0800
Subject: [PATCH] [analyzer] Simplify SVal for simple NonLoc->Loc casts

NonLoc symbolic SVal to Loc casts are not supported except for
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can
go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
long long t2 = t1 + 3;
if (!t2) {
  int *p = (int *) t2;
  clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
}
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p'
is unknown.

Fixes #62232
---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp |  3 +-
 .../symbol-simplification-nonloc-loc.cpp  | 28 ++-
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 2a47116db55a1ad..7e431f7e598c4cb 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
   }
   // Delegate to SValBuilder to process.
   SVal OrigV = state->getSVal(Ex, LCtx);
-  SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
+  SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
+  SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
   // Negate the result if we're treating the boolean as a signed i1
   if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
 V = svalBuilder.evalMinus(V.castAs());
diff --git a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp 
b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
index 485f68d9a5acfba..6cfe8da971429c3 100644
--- a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
+++ b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
@@ -1,6 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core %s \
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection %s \
 // RUN:-triple x86_64-pc-linux-gnu -verify
 
+void clang_analyzer_eval(int);
+
 #define BINOP(OP) [](auto x, auto y) { return x OP y; }
 
 template 
@@ -73,3 +75,27 @@ void zoo1backwards() {
   *(0 + p) = nullptr;  // warn
   **(0 + p) = 'a'; // no-warning: this should be unreachable
 }
+
+void test_simplified_before_cast_add(long t1) {
+  long t2 = t1 + 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_sub(long t1) {
+  long t2 = t1 - 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_mul(long t1) {
+  long t2 = t1 * 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/66463

>From d48b57387e3dc1c2f3fdeae00fe1596b3466638d Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Fri, 15 Sep 2023 14:01:26 +0800
Subject: [PATCH] [analyzer] Simplify SVal for simple NonLoc->Loc casts

NonLoc symbolic SVal to Loc casts are not supported except for
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can
go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
long long t2 = t1 + 3;
if (!t2) {
  int *p = (int *) t2;
  clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
}
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p'
is unknown.

Fixes #62232
---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp |  3 ++-
 .../symbol-simplification-nonloc-loc.cpp  | 26 +++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 2a47116db55a1ad..7e431f7e598c4cb 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
   }
   // Delegate to SValBuilder to process.
   SVal OrigV = state->getSVal(Ex, LCtx);
-  SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
+  SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
+  SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
   // Negate the result if we're treating the boolean as a signed i1
   if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
 V = svalBuilder.evalMinus(V.castAs());
diff --git a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp 
b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
index 485f68d9a5acfba..619fda824cb70b5 100644
--- a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
+++ b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core %s \
 // RUN:-triple x86_64-pc-linux-gnu -verify
 
+void clang_analyzer_eval(int);
+
 #define BINOP(OP) [](auto x, auto y) { return x OP y; }
 
 template 
@@ -73,3 +75,27 @@ void zoo1backwards() {
   *(0 + p) = nullptr;  // warn
   **(0 + p) = 'a'; // no-warning: this should be unreachable
 }
+
+void test_simplified_before_cast_add(long t1) {
+  long long t2 = t1 + 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_sub(long t1) {
+  long long t2 = t1 - 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_mul(long t1) {
+  long long t2 = t1 * 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -0,0 +1,31 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -verify
+
+void clang_analyzer_eval(int);
+
+void test_simplified_before_cast_add(long long t1) {
+  long long t2 = t1 + 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_sub(long long t1) {
+  long long t2 = t1 - 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_mul(long long t1) {
+  long long t2 = t1 * 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}

danix800 wrote:

Moved this into `symbol-simplification-nonloc-loc.cpp`.

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


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -0,0 +1,31 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -verify
+
+void clang_analyzer_eval(int);
+
+void test_simplified_before_cast_add(long long t1) {
+  long long t2 = t1 + 3;
+  if (!t2) {
+int *p = (int *) t2;

danix800 wrote:

I'll move this into `symbol-simplification-nonloc-loc.cpp` which already 
restrict that target to be `x86_64`.

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


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
   }
   // Delegate to SValBuilder to process.
   SVal OrigV = state->getSVal(Ex, LCtx);
-  SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
+  SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
+  SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);

danix800 wrote:

Bound value might not be used at all, so I think lazy simplification would be 
better.

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


[clang] [clang] fix lack comparison of declRefExpr in ASTStructuralEquivalence (PR #66041)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -2320,5 +2320,14 @@ TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookup) {
   EXPECT_TRUE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceStmtTest, DeclRefENoEq) {

danix800 wrote:

```suggestion
TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) {
```

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


[clang] [clang] fix lack comparison of declRefExpr in ASTStructuralEquivalence (PR #66041)

2023-09-15 Thread Ding Fei via cfe-commits


@@ -218,6 +218,8 @@ Bug Fixes in This Version
   (`#65156 `_)
 - Clang no longer considers the loss of ``__unaligned`` qualifier from objects 
as
   an invalid conversion during method function overload resolution.
+- Fix lack of comparison of declRefExpr in ASTStructuralEquivalence
+  (`#66047 `_`)

danix800 wrote:

```suggestion
  (`#66047 `_)
```

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


[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

2023-09-15 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/66463

NonLoc symbolic SVal to Loc casts are not supported except for 
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can go through 
nonloc::ConcreteInt->loc::ConcreteInt path. For example:

```c
  void test_simplified_before_cast_add(long long t1) {
long long t2 = t1 + 3;
if (!t2) {
  int *p = (int *) t2;
  clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
}
  }
```
If simplified, `t2` is 0, resulting `p` is nullptr, otherwise `p` is unknown.

Fixes #62232

>From e171f8ea4d0fea12dadad6b0ecaffba42ff6ba85 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Fri, 15 Sep 2023 14:01:26 +0800
Subject: [PATCH] [analyzer] Simplify SVal for simple NonLoc->Loc casts

NonLoc symbolic SVal to Loc casts are not supported except for
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can
go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
long long t2 = t1 + 3;
if (!t2) {
  int *p = (int *) t2;
  clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
}
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p'
is unknown.

Fixes #62232
---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp |  3 +-
 ...solver-sym-simplification-lvalue-bitcast.c | 31 +++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 
clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 2a47116db55a1ad..7e431f7e598c4cb 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
   }
   // Delegate to SValBuilder to process.
   SVal OrigV = state->getSVal(Ex, LCtx);
-  SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
+  SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
+  SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
   // Negate the result if we're treating the boolean as a signed i1
   if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
 V = svalBuilder.evalMinus(V.castAs());
diff --git a/clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c 
b/clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c
new file mode 100644
index 000..db8b1456527e523
--- /dev/null
+++ b/clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c
@@ -0,0 +1,31 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -verify
+
+void clang_analyzer_eval(int);
+
+void test_simplified_before_cast_add(long long t1) {
+  long long t2 = t1 + 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_sub(long long t1) {
+  long long t2 = t1 - 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_mul(long long t1) {
+  long long t2 = t1 * 3;
+  if (!t2) {
+int *p = (int *) t2;
+clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/65448:

>From 501595caf608aaeb8253235c32de5dd3ef4d3439 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH 1/3] [analyzer] Reduce constraint on modulo with small
 concrete range

---
 .../Core/RangeConstraintManager.cpp   | 48 +++
 clang/test/Analysis/constraint-assignor.c | 60 +++
 2 files changed, 108 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..9bda29c87f3c0f1 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2073,6 +2073,14 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (Sym->getOpcode() != BO_Rem)
   return true;
 // a % b != 0 implies that a != 0.
+// Z3 verification:
+//   (declare-const a Int)
+//   (declare-const m Int)
+//   (assert (not (= m 0)))
+//   (assert (not (= (mod a m) 0)))
+//   (assert (= a 0))
+//   (check-sat)
+//   ; unsat
 if (!Constraint.containsZero()) {
   SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
   if (auto NonLocSymSVal = SymSVal.getAs()) {
@@ -2080,6 +2088,46 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (!State)
   return false;
   }
+} else if (auto *SIE = dyn_cast(Sym);
+   SIE && Constraint.encodesFalseRange()) {
+  // a % m == 0 && a in [x, y] && y - x < m implies that
+  // a = (y < 0 ? x : y) / m * m which is a 'ConcreteInt'
+  // where x and m are 'ConcreteInt'.
+  //
+  // Z3 verification:
+  //   (declare-const a Int)
+  //   (declare-const m Int)
+  //   (declare-const x Int)
+  //   (declare-const y Int)
+  //   (assert (= (mod a m) 0))
+  //   (assert (< (- y x) m))
+  //   (assert (and (>= a x) (<= a y)))
+  //   (assert (not (= a (* (div y m) m
+  //   (check-sat)
+  //   ; unsat
+  llvm::APSInt Modulo = SIE->getRHS();
+  Modulo = llvm::APSInt(Modulo.abs(), Modulo.isUnsigned());
+  RangeSet RS =
+  SymbolicRangeInferrer::inferRange(RangeFactory, State, 
SIE->getLHS());
+  if (RS.size() == 1) {
+auto R = RS.begin();
+if ((R->To() - R->From()).getExtValue() < Modulo.getExtValue()) {
+  SVal SymSVal = Builder.makeSymbolVal(SIE->getLHS());
+  if (auto NonLocSymSVal = SymSVal.getAs()) {
+auto NewConstConstraint = Builder.makeIntVal(
+(R->To() > 0 ? R->To() : R->From()) / Modulo * Modulo);
+if (auto Cond = Builder
+.evalBinOp(State, BO_EQ, *NonLocSymSVal,
+   NewConstConstraint,
+   Builder.getConditionType())
+.template getAs()) {
+  State = State->assume(*Cond, true);
+  if (!State)
+return false;
+}
+  }
+}
+  }
 }
 return true;
   }
diff --git a/clang/test/Analysis/constraint-assignor.c 
b/clang/test/Analysis/constraint-assignor.c
index 8210e576c98bd21..150fe20c9f37a0a 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -5,6 +5,7 @@
 
 void clang_analyzer_warnIfReached(void);
 void clang_analyzer_eval(int);
+void clang_analyzer_dump(int);
 
 void rem_constant_rhs_ne_zero(int x, int y) {
   if (x % 3 == 0) // x % 3 != 0 -> x != 0
@@ -82,3 +83,62 @@ void remainder_with_adjustment_of_composit_lhs(int x, int y) 
{
   clang_analyzer_eval(x + y != -1);// expected-warning{{TRUE}}
   (void)(x * y); // keep the constraints alive.
 }
+
+void remainder_infeasible(int x, int y) {
+  if (x <= 2 || x >= 5)
+return;
+  if (x % 5 != 0)
+return;
+  clang_analyzer_warnIfReached(); // no-warning
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range_unsigned(unsigned x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range(int x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_range_spans_zero(int x) {
+  if (x <= -2 || x > 2)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{0 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void 

[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/65448:

>From 235f39a6a5137e53239105727798d4540e5dd563 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH 1/3] [analyzer] Reduce constraint on modulo with small
 concrete range

---
 .../Core/RangeConstraintManager.cpp   | 48 +++
 clang/test/Analysis/constraint-assignor.c | 60 +++
 2 files changed, 108 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..9bda29c87f3c0f1 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2073,6 +2073,14 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (Sym->getOpcode() != BO_Rem)
   return true;
 // a % b != 0 implies that a != 0.
+// Z3 verification:
+//   (declare-const a Int)
+//   (declare-const m Int)
+//   (assert (not (= m 0)))
+//   (assert (not (= (mod a m) 0)))
+//   (assert (= a 0))
+//   (check-sat)
+//   ; unsat
 if (!Constraint.containsZero()) {
   SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
   if (auto NonLocSymSVal = SymSVal.getAs()) {
@@ -2080,6 +2088,46 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (!State)
   return false;
   }
+} else if (auto *SIE = dyn_cast(Sym);
+   SIE && Constraint.encodesFalseRange()) {
+  // a % m == 0 && a in [x, y] && y - x < m implies that
+  // a = (y < 0 ? x : y) / m * m which is a 'ConcreteInt'
+  // where x and m are 'ConcreteInt'.
+  //
+  // Z3 verification:
+  //   (declare-const a Int)
+  //   (declare-const m Int)
+  //   (declare-const x Int)
+  //   (declare-const y Int)
+  //   (assert (= (mod a m) 0))
+  //   (assert (< (- y x) m))
+  //   (assert (and (>= a x) (<= a y)))
+  //   (assert (not (= a (* (div y m) m
+  //   (check-sat)
+  //   ; unsat
+  llvm::APSInt Modulo = SIE->getRHS();
+  Modulo = llvm::APSInt(Modulo.abs(), Modulo.isUnsigned());
+  RangeSet RS =
+  SymbolicRangeInferrer::inferRange(RangeFactory, State, 
SIE->getLHS());
+  if (RS.size() == 1) {
+auto R = RS.begin();
+if ((R->To() - R->From()).getExtValue() < Modulo.getExtValue()) {
+  SVal SymSVal = Builder.makeSymbolVal(SIE->getLHS());
+  if (auto NonLocSymSVal = SymSVal.getAs()) {
+auto NewConstConstraint = Builder.makeIntVal(
+(R->To() > 0 ? R->To() : R->From()) / Modulo * Modulo);
+if (auto Cond = Builder
+.evalBinOp(State, BO_EQ, *NonLocSymSVal,
+   NewConstConstraint,
+   Builder.getConditionType())
+.template getAs()) {
+  State = State->assume(*Cond, true);
+  if (!State)
+return false;
+}
+  }
+}
+  }
 }
 return true;
   }
diff --git a/clang/test/Analysis/constraint-assignor.c 
b/clang/test/Analysis/constraint-assignor.c
index 8210e576c98bd21..150fe20c9f37a0a 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -5,6 +5,7 @@
 
 void clang_analyzer_warnIfReached(void);
 void clang_analyzer_eval(int);
+void clang_analyzer_dump(int);
 
 void rem_constant_rhs_ne_zero(int x, int y) {
   if (x % 3 == 0) // x % 3 != 0 -> x != 0
@@ -82,3 +83,62 @@ void remainder_with_adjustment_of_composit_lhs(int x, int y) 
{
   clang_analyzer_eval(x + y != -1);// expected-warning{{TRUE}}
   (void)(x * y); // keep the constraints alive.
 }
+
+void remainder_infeasible(int x, int y) {
+  if (x <= 2 || x >= 5)
+return;
+  if (x % 5 != 0)
+return;
+  clang_analyzer_warnIfReached(); // no-warning
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range_unsigned(unsigned x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range(int x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_range_spans_zero(int x) {
+  if (x <= -2 || x > 2)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{0 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void 

[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-08 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-07 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/65448:

>From 235f39a6a5137e53239105727798d4540e5dd563 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH 1/2] [analyzer] Reduce constraint on modulo with small
 concrete range

---
 .../Core/RangeConstraintManager.cpp   | 48 +++
 clang/test/Analysis/constraint-assignor.c | 60 +++
 2 files changed, 108 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..9bda29c87f3c0f1 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2073,6 +2073,14 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (Sym->getOpcode() != BO_Rem)
   return true;
 // a % b != 0 implies that a != 0.
+// Z3 verification:
+//   (declare-const a Int)
+//   (declare-const m Int)
+//   (assert (not (= m 0)))
+//   (assert (not (= (mod a m) 0)))
+//   (assert (= a 0))
+//   (check-sat)
+//   ; unsat
 if (!Constraint.containsZero()) {
   SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
   if (auto NonLocSymSVal = SymSVal.getAs()) {
@@ -2080,6 +2088,46 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (!State)
   return false;
   }
+} else if (auto *SIE = dyn_cast(Sym);
+   SIE && Constraint.encodesFalseRange()) {
+  // a % m == 0 && a in [x, y] && y - x < m implies that
+  // a = (y < 0 ? x : y) / m * m which is a 'ConcreteInt'
+  // where x and m are 'ConcreteInt'.
+  //
+  // Z3 verification:
+  //   (declare-const a Int)
+  //   (declare-const m Int)
+  //   (declare-const x Int)
+  //   (declare-const y Int)
+  //   (assert (= (mod a m) 0))
+  //   (assert (< (- y x) m))
+  //   (assert (and (>= a x) (<= a y)))
+  //   (assert (not (= a (* (div y m) m
+  //   (check-sat)
+  //   ; unsat
+  llvm::APSInt Modulo = SIE->getRHS();
+  Modulo = llvm::APSInt(Modulo.abs(), Modulo.isUnsigned());
+  RangeSet RS =
+  SymbolicRangeInferrer::inferRange(RangeFactory, State, 
SIE->getLHS());
+  if (RS.size() == 1) {
+auto R = RS.begin();
+if ((R->To() - R->From()).getExtValue() < Modulo.getExtValue()) {
+  SVal SymSVal = Builder.makeSymbolVal(SIE->getLHS());
+  if (auto NonLocSymSVal = SymSVal.getAs()) {
+auto NewConstConstraint = Builder.makeIntVal(
+(R->To() > 0 ? R->To() : R->From()) / Modulo * Modulo);
+if (auto Cond = Builder
+.evalBinOp(State, BO_EQ, *NonLocSymSVal,
+   NewConstConstraint,
+   Builder.getConditionType())
+.template getAs()) {
+  State = State->assume(*Cond, true);
+  if (!State)
+return false;
+}
+  }
+}
+  }
 }
 return true;
   }
diff --git a/clang/test/Analysis/constraint-assignor.c 
b/clang/test/Analysis/constraint-assignor.c
index 8210e576c98bd21..150fe20c9f37a0a 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -5,6 +5,7 @@
 
 void clang_analyzer_warnIfReached(void);
 void clang_analyzer_eval(int);
+void clang_analyzer_dump(int);
 
 void rem_constant_rhs_ne_zero(int x, int y) {
   if (x % 3 == 0) // x % 3 != 0 -> x != 0
@@ -82,3 +83,62 @@ void remainder_with_adjustment_of_composit_lhs(int x, int y) 
{
   clang_analyzer_eval(x + y != -1);// expected-warning{{TRUE}}
   (void)(x * y); // keep the constraints alive.
 }
+
+void remainder_infeasible(int x, int y) {
+  if (x <= 2 || x >= 5)
+return;
+  if (x % 5 != 0)
+return;
+  clang_analyzer_warnIfReached(); // no-warning
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range_unsigned(unsigned x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range(int x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_range_spans_zero(int x) {
+  if (x <= -2 || x > 2)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{0 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void 

[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-07 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-07 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-07 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-07 Thread Ding Fei via cfe-commits

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


[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-07 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/65448:

>From 235f39a6a5137e53239105727798d4540e5dd563 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH 1/2] [analyzer] Reduce constraint on modulo with small
 concrete range

---
 .../Core/RangeConstraintManager.cpp   | 48 +++
 clang/test/Analysis/constraint-assignor.c | 60 +++
 2 files changed, 108 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..9bda29c87f3c0f1 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2073,6 +2073,14 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (Sym->getOpcode() != BO_Rem)
   return true;
 // a % b != 0 implies that a != 0.
+// Z3 verification:
+//   (declare-const a Int)
+//   (declare-const m Int)
+//   (assert (not (= m 0)))
+//   (assert (not (= (mod a m) 0)))
+//   (assert (= a 0))
+//   (check-sat)
+//   ; unsat
 if (!Constraint.containsZero()) {
   SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
   if (auto NonLocSymSVal = SymSVal.getAs()) {
@@ -2080,6 +2088,46 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (!State)
   return false;
   }
+} else if (auto *SIE = dyn_cast(Sym);
+   SIE && Constraint.encodesFalseRange()) {
+  // a % m == 0 && a in [x, y] && y - x < m implies that
+  // a = (y < 0 ? x : y) / m * m which is a 'ConcreteInt'
+  // where x and m are 'ConcreteInt'.
+  //
+  // Z3 verification:
+  //   (declare-const a Int)
+  //   (declare-const m Int)
+  //   (declare-const x Int)
+  //   (declare-const y Int)
+  //   (assert (= (mod a m) 0))
+  //   (assert (< (- y x) m))
+  //   (assert (and (>= a x) (<= a y)))
+  //   (assert (not (= a (* (div y m) m
+  //   (check-sat)
+  //   ; unsat
+  llvm::APSInt Modulo = SIE->getRHS();
+  Modulo = llvm::APSInt(Modulo.abs(), Modulo.isUnsigned());
+  RangeSet RS =
+  SymbolicRangeInferrer::inferRange(RangeFactory, State, 
SIE->getLHS());
+  if (RS.size() == 1) {
+auto R = RS.begin();
+if ((R->To() - R->From()).getExtValue() < Modulo.getExtValue()) {
+  SVal SymSVal = Builder.makeSymbolVal(SIE->getLHS());
+  if (auto NonLocSymSVal = SymSVal.getAs()) {
+auto NewConstConstraint = Builder.makeIntVal(
+(R->To() > 0 ? R->To() : R->From()) / Modulo * Modulo);
+if (auto Cond = Builder
+.evalBinOp(State, BO_EQ, *NonLocSymSVal,
+   NewConstConstraint,
+   Builder.getConditionType())
+.template getAs()) {
+  State = State->assume(*Cond, true);
+  if (!State)
+return false;
+}
+  }
+}
+  }
 }
 return true;
   }
diff --git a/clang/test/Analysis/constraint-assignor.c 
b/clang/test/Analysis/constraint-assignor.c
index 8210e576c98bd21..150fe20c9f37a0a 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -5,6 +5,7 @@
 
 void clang_analyzer_warnIfReached(void);
 void clang_analyzer_eval(int);
+void clang_analyzer_dump(int);
 
 void rem_constant_rhs_ne_zero(int x, int y) {
   if (x % 3 == 0) // x % 3 != 0 -> x != 0
@@ -82,3 +83,62 @@ void remainder_with_adjustment_of_composit_lhs(int x, int y) 
{
   clang_analyzer_eval(x + y != -1);// expected-warning{{TRUE}}
   (void)(x * y); // keep the constraints alive.
 }
+
+void remainder_infeasible(int x, int y) {
+  if (x <= 2 || x >= 5)
+return;
+  if (x % 5 != 0)
+return;
+  clang_analyzer_warnIfReached(); // no-warning
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range_unsigned(unsigned x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range(int x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_range_spans_zero(int x) {
+  if (x <= -2 || x > 2)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{0 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void 

[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-06 Thread Ding Fei via cfe-commits

https://github.com/danix800 updated 
https://github.com/llvm/llvm-project/pull/65448:

>From 235f39a6a5137e53239105727798d4540e5dd563 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH] [analyzer] Reduce constraint on modulo with small concrete
 range

---
 .../Core/RangeConstraintManager.cpp   | 48 +++
 clang/test/Analysis/constraint-assignor.c | 60 +++
 2 files changed, 108 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c..9bda29c87f3c0f 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2073,6 +2073,14 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (Sym->getOpcode() != BO_Rem)
   return true;
 // a % b != 0 implies that a != 0.
+// Z3 verification:
+//   (declare-const a Int)
+//   (declare-const m Int)
+//   (assert (not (= m 0)))
+//   (assert (not (= (mod a m) 0)))
+//   (assert (= a 0))
+//   (check-sat)
+//   ; unsat
 if (!Constraint.containsZero()) {
   SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
   if (auto NonLocSymSVal = SymSVal.getAs()) {
@@ -2080,6 +2088,46 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (!State)
   return false;
   }
+} else if (auto *SIE = dyn_cast(Sym);
+   SIE && Constraint.encodesFalseRange()) {
+  // a % m == 0 && a in [x, y] && y - x < m implies that
+  // a = (y < 0 ? x : y) / m * m which is a 'ConcreteInt'
+  // where x and m are 'ConcreteInt'.
+  //
+  // Z3 verification:
+  //   (declare-const a Int)
+  //   (declare-const m Int)
+  //   (declare-const x Int)
+  //   (declare-const y Int)
+  //   (assert (= (mod a m) 0))
+  //   (assert (< (- y x) m))
+  //   (assert (and (>= a x) (<= a y)))
+  //   (assert (not (= a (* (div y m) m
+  //   (check-sat)
+  //   ; unsat
+  llvm::APSInt Modulo = SIE->getRHS();
+  Modulo = llvm::APSInt(Modulo.abs(), Modulo.isUnsigned());
+  RangeSet RS =
+  SymbolicRangeInferrer::inferRange(RangeFactory, State, 
SIE->getLHS());
+  if (RS.size() == 1) {
+auto R = RS.begin();
+if ((R->To() - R->From()).getExtValue() < Modulo.getExtValue()) {
+  SVal SymSVal = Builder.makeSymbolVal(SIE->getLHS());
+  if (auto NonLocSymSVal = SymSVal.getAs()) {
+auto NewConstConstraint = Builder.makeIntVal(
+(R->To() > 0 ? R->To() : R->From()) / Modulo * Modulo);
+if (auto Cond = Builder
+.evalBinOp(State, BO_EQ, *NonLocSymSVal,
+   NewConstConstraint,
+   Builder.getConditionType())
+.template getAs()) {
+  State = State->assume(*Cond, true);
+  if (!State)
+return false;
+}
+  }
+}
+  }
 }
 return true;
   }
diff --git a/clang/test/Analysis/constraint-assignor.c 
b/clang/test/Analysis/constraint-assignor.c
index 8210e576c98bd2..150fe20c9f37a0 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -5,6 +5,7 @@
 
 void clang_analyzer_warnIfReached(void);
 void clang_analyzer_eval(int);
+void clang_analyzer_dump(int);
 
 void rem_constant_rhs_ne_zero(int x, int y) {
   if (x % 3 == 0) // x % 3 != 0 -> x != 0
@@ -82,3 +83,62 @@ void remainder_with_adjustment_of_composit_lhs(int x, int y) 
{
   clang_analyzer_eval(x + y != -1);// expected-warning{{TRUE}}
   (void)(x * y); // keep the constraints alive.
 }
+
+void remainder_infeasible(int x, int y) {
+  if (x <= 2 || x >= 5)
+return;
+  if (x % 5 != 0)
+return;
+  clang_analyzer_warnIfReached(); // no-warning
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range_unsigned(unsigned x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_positive_range(int x) {
+  if (x <= 2 || x > 6)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{5 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_within_modulo_range_spans_zero(int x) {
+  if (x <= -2 || x > 2)
+return;
+  clang_analyzer_dump(x); // expected-warning{{reg_$0}}
+  if (x % 5 != 0)
+return;
+  clang_analyzer_dump(x);  // expected-warning{{0 S32b}}
+  (void)x; // keep the constraints alive.
+}
+
+void 

[clang] [analyzer] Reduce constraint on modulo with small concrete range (PR #65448)

2023-09-06 Thread Ding Fei via cfe-commits

https://github.com/danix800 created 
https://github.com/llvm/llvm-project/pull/65448:

Fixes #54377

>From 2b04f714f1e1985546ff7ed00c131591316782b8 Mon Sep 17 00:00:00 2001
From: dingfei 
Date: Wed, 6 Sep 2023 10:03:21 +0800
Subject: [PATCH] [analyzer] Reduce constraint on modulo with small concrete
 range

---
 .../PathSensitive/RangedConstraintManager.h   |  1 +
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  |  3 +
 .../Core/RangeConstraintManager.cpp   | 48 +++
 .../Core/RangedConstraintManager.cpp  | 14 +
 clang/test/Analysis/constraint-assignor.c | 60 +++
 5 files changed, 126 insertions(+)

diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
index 49ea006e27aa54..f350cfa1cd011c 100644
--- 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
+++ 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
@@ -476,6 +476,7 @@ class RangedConstraintManager : public 
SimpleConstraintManager {
   //===--===//
 private:
   static void computeAdjustment(SymbolRef , llvm::APSInt );
+  static void computeScaling(SymbolRef , llvm::APSInt );
 };
 
 /// Try to simplify a given symbolic expression based on the constraints in
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0e2ac78f7089c5..670de6795f1c2d 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1702,6 +1702,9 @@ ProgramStateRef ExprEngine::escapeValues(ProgramStateRef 
State,
 
 void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet ) {
+  //  static int Count = 0;
+  //  llvm::errs() << "Count: " << Count++ << "\n";
+  //  S->dump();
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
 S->getBeginLoc(), "Error evaluating 
statement");
   ExplodedNodeSet Dst;
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c..9bda29c87f3c0f 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2073,6 +2073,14 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (Sym->getOpcode() != BO_Rem)
   return true;
 // a % b != 0 implies that a != 0.
+// Z3 verification:
+//   (declare-const a Int)
+//   (declare-const m Int)
+//   (assert (not (= m 0)))
+//   (assert (not (= (mod a m) 0)))
+//   (assert (= a 0))
+//   (check-sat)
+//   ; unsat
 if (!Constraint.containsZero()) {
   SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
   if (auto NonLocSymSVal = SymSVal.getAs()) {
@@ -2080,6 +2088,46 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 if (!State)
   return false;
   }
+} else if (auto *SIE = dyn_cast(Sym);
+   SIE && Constraint.encodesFalseRange()) {
+  // a % m == 0 && a in [x, y] && y - x < m implies that
+  // a = (y < 0 ? x : y) / m * m which is a 'ConcreteInt'
+  // where x and m are 'ConcreteInt'.
+  //
+  // Z3 verification:
+  //   (declare-const a Int)
+  //   (declare-const m Int)
+  //   (declare-const x Int)
+  //   (declare-const y Int)
+  //   (assert (= (mod a m) 0))
+  //   (assert (< (- y x) m))
+  //   (assert (and (>= a x) (<= a y)))
+  //   (assert (not (= a (* (div y m) m
+  //   (check-sat)
+  //   ; unsat
+  llvm::APSInt Modulo = SIE->getRHS();
+  Modulo = llvm::APSInt(Modulo.abs(), Modulo.isUnsigned());
+  RangeSet RS =
+  SymbolicRangeInferrer::inferRange(RangeFactory, State, 
SIE->getLHS());
+  if (RS.size() == 1) {
+auto R = RS.begin();
+if ((R->To() - R->From()).getExtValue() < Modulo.getExtValue()) {
+  SVal SymSVal = Builder.makeSymbolVal(SIE->getLHS());
+  if (auto NonLocSymSVal = SymSVal.getAs()) {
+auto NewConstConstraint = Builder.makeIntVal(
+(R->To() > 0 ? R->To() : R->From()) / Modulo * Modulo);
+if (auto Cond = Builder
+.evalBinOp(State, BO_EQ, *NonLocSymSVal,
+   NewConstConstraint,
+   Builder.getConditionType())
+.template getAs()) {
+  State = State->assume(*Cond, true);
+  if (!State)
+return false;
+}
+  }
+}
+  }
 }
 return true;
   }
diff --git a/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp 

[clang-tools-extra] [clang-tidy][misc-include-cleaner]Avoid to insert same include header multiple times (PR #65431)

2023-09-05 Thread Ding Fei via cfe-commits


@@ -209,14 +212,16 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult ) {
 // main file.
 if (auto Replacement =
 HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),

danix800 wrote:

`HeaderIncludes` is NOT a container. This `insert` means to create a 
`tooling::Replacement` object rather than container insertion/emplacing.

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


[clang-tools-extra] [clang-tidy][misc-include-cleaner]Avoid to insert same include header multiple times (PR #65431)

2023-09-05 Thread Ding Fei via cfe-commits

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


[clang-tools-extra] [clang-tidy][misc-include-cleaner]Avoid to insert same include header multiple times (PR #65431)

2023-09-05 Thread Ding Fei via cfe-commits


@@ -199,6 +199,9 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult ) {
 
   tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
  FileStyle->IncludeStyle);
+  // `tooling::HeaderIncludes::insert` will not modify `ExistingIncludes`. We
+  // should handle repeat include here
+  std::set InsertedHeader{};

danix800 wrote:

`std::set` won't compile, please take a look at the failed 
CI checking. `llvm::StringSet` might be better option if `std::string` could be 
switched to `StringRef`.

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


[clang-tools-extra] [clang-tidy][misc-include-cleaner]Avoid to insert same include header multiple times (PR #65431)

2023-09-05 Thread Ding Fei via cfe-commits

danix800 wrote:

Please refer to https://reviews.llvm.org/D159263 about `areDiagsSelfContained`.

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