[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-28 Thread Alan Zhao via cfe-commits

alanzhao1 wrote:

FYI this patch messes up some diagnostics with `-Wunreachable-code`: 
https://godbolt.org/z/6TEdrx55d

If the unreachable code is a constructor with a default parameter that is a 
builtin function, clang incorrectly highlights the call to the builtin instead 
of the call to the constructor.

There's a similar issue if instead of a builtin the default parameter is the 
return value of another function which itself has default parameter that is a 
builtin: https://godbolt.org/z/ErarnbGbY

This was originally observed in Chrome - see https://crbug.com/343231820.



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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits

yronglin wrote:

Thanks for your review! The CI did 
passed(https://buildkite.com/llvm-project/github-pull-requests/builds/66630) 
but not shown on github for whatever reason.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread Balazs Benics via cfe-commits

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

LGTM, thanks!

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/91879

>From f7b2ae00eebb272e0e5e221608ec3a36146a5d21 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Sun, 12 May 2024 14:42:09 +0800
Subject: [PATCH 1/5] [Analyzer][CFG] Correctly handle rebuilted default arg
 and default init expression

Signed-off-by: yronglin 
---
 clang/lib/AST/ParentMap.cpp  | 16 +
 clang/lib/Analysis/CFG.cpp   | 38 +++-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..2f3f3e92516ba 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,8 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, ILE)) {
 autoCreateBlock();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0b1edf3e5c96b..41cb4293a8451 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
-
-  ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   const Expr *ArgE;
   if (const auto *DefE = dyn_cast(S))
@@ -1978,25 +1975,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
   else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = fals

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits


@@ -1114,17 +1114,16 @@ void fCXX11MemberInitTest1() {
   CXX11MemberInitTest1();
 }
 
+#ifdef PEDANTIC

yronglin wrote:

done

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);
+}
+  } else {
+// If it's not rewritten, the contents of these expressions are not
+// actually part of the current function, so we fall back to constant
+// evaluation.
+bool IsTemporary = false;
+if (const auto *MTE = dyn_cast(ArgE)) {
+  ArgE = MTE->getSubExpr();
+  IsTemporary = true;
+}
+
+std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
+if (!ConstantVal)
+  ConstantVal = UnknownVal();
 
-  std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
-  if (!ConstantVal)
-ConstantVal = UnknownVal();
-
-  const LocationContext *LCtx = Pred->getLocationContext();
-  for (const auto I : PreVisit) {
-ProgramStateRef State = I->getState();
-State = State->BindExpr(S, LCtx, *ConstantVal);
-if (IsTemporary)
-  State = createTemporaryRegionIfNeeded(State, LCtx,
-cast(S),
-cast(S));
-Bldr2.generateNode(S, I, State);
+const LocationContext *LCtx = Pred->getLocationContext();
+for (auto *I : CheckedSet) {
+  ProgramStateRef State = I->getState();
+  State = State->BindExpr(S, LCtx, *ConstantVal);

yronglin wrote:

done

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);
+}
+  } else {
+// If it's not rewritten, the contents of these expressions are not
+// actually part of the current function, so we fall back to constant
+// evaluation.
+bool IsTemporary = false;
+if (const auto *MTE = dyn_cast(ArgE)) {
+  ArgE = MTE->getSubExpr();
+  IsTemporary = true;
+}
+
+std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
+if (!ConstantVal)
+  ConstantVal = UnknownVal();

yronglin wrote:

done

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);

yronglin wrote:

done

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-23 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/91879

>From f7b2ae00eebb272e0e5e221608ec3a36146a5d21 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Sun, 12 May 2024 14:42:09 +0800
Subject: [PATCH 1/4] [Analyzer][CFG] Correctly handle rebuilted default arg
 and default init expression

Signed-off-by: yronglin 
---
 clang/lib/AST/ParentMap.cpp  | 16 +
 clang/lib/Analysis/CFG.cpp   | 38 +++-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..2f3f3e92516ba 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,8 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, ILE)) {
 autoCreateBlock();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0b1edf3e5c96b..41cb4293a8451 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
-
-  ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   const Expr *ArgE;
   if (const auto *DefE = dyn_cast(S))
@@ -1978,25 +1975,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
   else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = fals

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-17 Thread via cfe-commits


@@ -5905,7 +5907,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation 
Loc, FieldDecl *Field) {
 
 return CXXDefaultInitExpr::Create(Context, InitializationContext->Loc,
   Field, InitializationContext->Context,
-  Init);
+  HasRewrittenInit ? Init : nullptr);

yronglin wrote:

@cor3ntin Could you please help confirm this change is make sense?

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-17 Thread via cfe-commits

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-17 Thread via cfe-commits

yronglin wrote:

@steakhal Thanks for your review and sorry for the late reply! 
https://github.com/llvm/llvm-project/pull/87933 has been revert due to 
regression, I've a new PR to reapply 
CWG1815(https://github.com/llvm/llvm-project/pull/92527). I'll continue cook 
this PR once https://github.com/llvm/llvm-project/pull/92527 merged.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-17 Thread via cfe-commits


@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -std=c++14 -verify  %s \
+// RUN: %clang_analyze_cc1 -std=c++14 -verify=expected,pedantic  %s \

yronglin wrote:

It's used like the `pedantic-warning`, I'll remove this to address previous 
comments.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-17 Thread via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);
+}
+  } else {
+// If it's not rewritten, the contents of these expressions are not
+// actually part of the current function, so we fall back to constant
+// evaluation.
+bool IsTemporary = false;
+if (const auto *MTE = dyn_cast(ArgE)) {
+  ArgE = MTE->getSubExpr();
+  IsTemporary = true;
+}
+
+std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
+if (!ConstantVal)
+  ConstantVal = UnknownVal();

yronglin wrote:

Agree!

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-17 Thread via cfe-commits


@@ -1114,17 +1114,16 @@ void fCXX11MemberInitTest1() {
   CXX11MemberInitTest1();
 }
 
+#ifdef PEDANTIC

yronglin wrote:

Agree!

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);

steakhal wrote:

```suggestion
for (ExplodedNode *N : CheckedSet) {
  ProgramStateRef State = N->getState();
  const LocationContext *LCtx = N->getLocationContext();
  State = State->BindExpr(S, LCtx, State->getSVal(ArgE, LCtx));
  Bldr2.generateNode(S, N, State);
```

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits


@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -std=c++14 -verify  %s \
+// RUN: %clang_analyze_cc1 -std=c++14 -verify=expected,pedantic  %s \

steakhal wrote:

You introduced the `pedantic` verify prefix, but never actually used it.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;

steakhal wrote:

I think I'd prefer the old name here. That is how one would find these in the 
other places.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits


@@ -1114,17 +1114,16 @@ void fCXX11MemberInitTest1() {
   CXX11MemberInitTest1();
 }
 
+#ifdef PEDANTIC

steakhal wrote:

I don't think you need to guard this section of code if you were using `// 
pedantic-note {{...}}` and `// pedantic-warning {{...}}` in the guarded checks.

I also think that the `// TODO: we'd expect the warning: {{2 uninitializeds 
field}}` comment refers to this new appearing report, so you should just drop 
that comment from the `fCXX11MemberInitTest2` function.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits

https://github.com/steakhal commented:

In general, this PR looks good to me.
I only have some nits inline.

If it didn't break anything, it should be good to go.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);
+}
+  } else {
+// If it's not rewritten, the contents of these expressions are not
+// actually part of the current function, so we fall back to constant
+// evaluation.
+bool IsTemporary = false;
+if (const auto *MTE = dyn_cast(ArgE)) {
+  ArgE = MTE->getSubExpr();
+  IsTemporary = true;
+}
+
+std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
+if (!ConstantVal)
+  ConstantVal = UnknownVal();

steakhal wrote:

```suggestion
```
I'd just drop this and use `value_or()` at the only use-site instead.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits


@@ -1964,39 +1964,55 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx);
 
-  const Expr *ArgE;
-  if (const auto *DefE = dyn_cast(S))
+  bool HasRewrittenInit = false;
+  const Expr *ArgE = nullptr;
+  if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else if (const auto *DefE = dyn_cast(S))
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else if (const auto *DefE = dyn_cast(S)) {
 ArgE = DefE->getExpr();
-  else
+HasRewrittenInit = DefE->hasRewrittenInit();
+  } else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-  if (const auto *MTE = dyn_cast(ArgE)) {
-ArgE = MTE->getSubExpr();
-IsTemporary = true;
-  }
+  if (HasRewrittenInit) {
+for (auto *I : CheckedSet) {
+  ProgramStateRef state = (*I).getState();
+  const LocationContext *LCtx = (*I).getLocationContext();
+  SVal Val = state->getSVal(ArgE, LCtx);
+  state = state->BindExpr(S, LCtx, Val);
+  Bldr2.generateNode(S, I, state);
+}
+  } else {
+// If it's not rewritten, the contents of these expressions are not
+// actually part of the current function, so we fall back to constant
+// evaluation.
+bool IsTemporary = false;
+if (const auto *MTE = dyn_cast(ArgE)) {
+  ArgE = MTE->getSubExpr();
+  IsTemporary = true;
+}
+
+std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
+if (!ConstantVal)
+  ConstantVal = UnknownVal();
 
-  std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
-  if (!ConstantVal)
-ConstantVal = UnknownVal();
-
-  const LocationContext *LCtx = Pred->getLocationContext();
-  for (const auto I : PreVisit) {
-ProgramStateRef State = I->getState();
-State = State->BindExpr(S, LCtx, *ConstantVal);
-if (IsTemporary)
-  State = createTemporaryRegionIfNeeded(State, LCtx,
-cast(S),
-cast(S));
-Bldr2.generateNode(S, I, State);
+const LocationContext *LCtx = Pred->getLocationContext();
+for (auto *I : CheckedSet) {
+  ProgramStateRef State = I->getState();
+  State = State->BindExpr(S, LCtx, *ConstantVal);

steakhal wrote:

```suggestion
  State = State->BindExpr(S, LCtx, ConstantVal.value_or(UnknownVal()));
```

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-14 Thread Balazs Benics via cfe-commits

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/91879

>From 6969f06f39363deda92d473ec14a08663c71f3b1 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Sun, 12 May 2024 14:42:09 +0800
Subject: [PATCH 1/3] [Analyzer][CFG] Correctly handle rebuilted default arg
 and default init expression

Signed-off-by: yronglin 
---
 clang/lib/AST/ParentMap.cpp  | 16 +
 clang/lib/Analysis/CFG.cpp   | 38 +++-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..2f3f3e92516ba 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,8 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, ILE)) {
 autoCreateBlock();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0b1edf3e5c96b..41cb4293a8451 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
-
-  ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   const Expr *ArgE;
   if (const auto *DefE = dyn_cast(S))
@@ -1978,25 +1975,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
   else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = fals

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits


@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);

yronglin wrote:

I've explicit specific `HasRewrittenInit` in `BuildCXXDefaultInitExpr` when 
construct `CXXDefaultInitExpr`. This solution is temporarily feasible, but it 
may not be a good way.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-static-analyzer-1

Author: None (yronglin)


Changes

Depends on https://github.com/llvm/llvm-project/pull/87933

Clang now support the following:
- Extending lifetime of object bound to reference members of aggregates, that 
are created from default member initializer. 
- Rebuild `CXXDefaultArgExpr` and `CXXDefaultInitExpr` as needed where called 
or constructed.

But CFG and ExprEngine need to be updated to address this change.

This PR add `CXXDefaultArgExpr` and `CXXDefaultInitExpr` into CFG, and correct 
handle these expressions in ExprEngine

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


6 Files Affected:

- (modified) clang/lib/AST/ParentMap.cpp (+16) 
- (modified) clang/lib/Analysis/CFG.cpp (+41-9) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+3-1) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+40-24) 
- (modified) clang/test/Analysis/cxx-uninitialized-object.cpp (+7-6) 
- (modified) clang/test/Analysis/lifetime-extended-regions.cpp (+3-4) 


``diff
diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..02317257c2740 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,10 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default,
+   AddStmtChoice asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default,
+AddStmtChoice asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2258,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2431,40 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+
+  // We can't add the default argument if it's not rewritten because the
+  // expression inside a CXXDefaultArgExpr is owned by the called function's
+  // declaration, not by the caller, we could end up with the same expression
+  // appearing multiple times.
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+
+  // We can't add the default initializer if it's not rewritten because 
multiple
+  // CXXDefaultInitExprs for the same sub-expression to be used in the same
+  // function (through aggregate initialization). we could end up with the same
+  // expression appearing multiple times.
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtCho

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (yronglin)


Changes

Depends on https://github.com/llvm/llvm-project/pull/87933

Clang now support the following:
- Extending lifetime of object bound to reference members of aggregates, that 
are created from default member initializer. 
- Rebuild `CXXDefaultArgExpr` and `CXXDefaultInitExpr` as needed where called 
or constructed.

But CFG and ExprEngine need to be updated to address this change.

This PR add `CXXDefaultArgExpr` and `CXXDefaultInitExpr` into CFG, and correct 
handle these expressions in ExprEngine

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


6 Files Affected:

- (modified) clang/lib/AST/ParentMap.cpp (+16) 
- (modified) clang/lib/Analysis/CFG.cpp (+41-9) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+3-1) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+40-24) 
- (modified) clang/test/Analysis/cxx-uninitialized-object.cpp (+7-6) 
- (modified) clang/test/Analysis/lifetime-extended-regions.cpp (+3-4) 


``diff
diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..02317257c2740 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,10 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default,
+   AddStmtChoice asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default,
+AddStmtChoice asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2258,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2431,40 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+
+  // We can't add the default argument if it's not rewritten because the
+  // expression inside a CXXDefaultArgExpr is owned by the called function's
+  // declaration, not by the caller, we could end up with the same expression
+  // appearing multiple times.
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+
+  // We can't add the default initializer if it's not rewritten because 
multiple
+  // CXXDefaultInitExprs for the same sub-expression to be used in the same
+  // function (through aggregate initialization). we could end up with the same
+  // expression appearing multiple times.
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/91879

>From 6969f06f39363deda92d473ec14a08663c71f3b1 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Sun, 12 May 2024 14:42:09 +0800
Subject: [PATCH 1/2] [Analyzer][CFG] Correctly handle rebuilted default arg
 and default init expression

Signed-off-by: yronglin 
---
 clang/lib/AST/ParentMap.cpp  | 16 +
 clang/lib/Analysis/CFG.cpp   | 38 +++-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..2f3f3e92516ba 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,8 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, ILE)) {
 autoCreateBlock();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0b1edf3e5c96b..41cb4293a8451 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
-
-  ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   const Expr *ArgE;
   if (const auto *DefE = dyn_cast(S))
@@ -1978,25 +1975,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
   else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = fals

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-13 Thread via cfe-commits

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-12 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/91879

>From 6969f06f39363deda92d473ec14a08663c71f3b1 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Sun, 12 May 2024 14:42:09 +0800
Subject: [PATCH] [Analyzer][CFG] Correctly handle rebuilted default arg and
 default init expression

Signed-off-by: yronglin 
---
 clang/lib/AST/ParentMap.cpp  | 16 +
 clang/lib/Analysis/CFG.cpp   | 38 +++-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..2f3f3e92516ba 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,8 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, ILE)) {
 autoCreateBlock();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0b1edf3e5c96b..41cb4293a8451 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
-
-  ExplodedNodeSet Tmp;
-  StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this);
 
   const Expr *ArgE;
   if (const auto *DefE = dyn_cast(S))
@@ -1978,25 +1975,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
   else
 llvm_unreachable("unknown constant wrapper kind");
 
-  bool IsTemporary = false;
-

[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-12 Thread via cfe-commits


@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);

yronglin wrote:

Thanks a lot for your review!

> I think it'd be useful to keep some of the old comment here: we can't add the 
> default argument if it's not rewritten because we could end up with the same 
> expression appearing multiple times.

Agree 100%, keep the old comment here can make things more clear. 

> Actually, are we safe from that even if the default argument is rewritten? Do 
> we guarantee to recreate all subexpressions in that case?

Not exactly, The rebuild implementation is the following, it's ignores 
`LambdaExpr`, `BlockExpr` and `CXXThisExpr`, And 
`EnsureImmediateInvocationInDefaultArgs`’s name may need to be refine.
https://github.com/llvm/llvm-project/blob/78b3a00418ce6da0426a261a64a77608d0264fe5/clang/lib/Sema/SemaExpr.cpp#L5707-L5723
 

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-12 Thread Richard Smith via cfe-commits


@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);

zygoloid wrote:

Actually, are we safe from that even if the default argument is rewritten? Do 
we guarantee to recreate all subexpressions in that case?

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-12 Thread Richard Smith via cfe-commits


@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);

zygoloid wrote:

I think it'd be useful to keep some of the old comment here: we can't add the 
default argument if it's not rewritten because we could end up with the same 
expression appearing multiple times.

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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-11 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 23fe1fc6b78b7643a801ce3eb53d14b47b1dd0ff 
6969f06f39363deda92d473ec14a08663c71f3b1 -- clang/lib/AST/ParentMap.cpp 
clang/lib/Analysis/CFG.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 2f3f3e9251..12a1634a31 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,8 +556,10 @@ public:
 
 private:
   // Visitors to walk an AST and construct the CFG.
-  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
-  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default,
+   AddStmtChoice asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default,
+AddStmtChoice asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);

``




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


[clang] [Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (PR #91879)

2024-05-11 Thread via cfe-commits

https://github.com/yronglin created 
https://github.com/llvm/llvm-project/pull/91879

Depends on https://github.com/llvm/llvm-project/pull/87933

Clang now support the following:
- Extending lifetime of object bound to reference members of aggregates, that 
are created from default member initializer. 
- Rebuild `CXXDefaultArgExpr` and `CXXDefaultInitExpr` as needed where called 
or constructed.

But CFG and ExprEngine need to be updated to address this change.

This PR add `CXXDefaultArgExpr` and `CXXDefaultInitExpr` into CFG, and correct 
handle these expressions in ExprEngine

>From 6969f06f39363deda92d473ec14a08663c71f3b1 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Sun, 12 May 2024 14:42:09 +0800
Subject: [PATCH] [Analyzer][CFG] Correctly handle rebuilted default arg and
 default init expression

Signed-off-by: yronglin 
---
 clang/lib/AST/ParentMap.cpp  | 16 +
 clang/lib/Analysis/CFG.cpp   | 38 +++-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index 3d6a1cc84c7b1..534793b837bbb 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S,
   BuildParentMap(M, SubStmt, OVMode);
 }
 break;
+  case Stmt::CXXDefaultArgExprClass:
+if (auto *Arg = dyn_cast(S)) {
+  if (Arg->hasRewrittenInit()) {
+M[Arg->getExpr()] = S;
+BuildParentMap(M, Arg->getExpr(), OVMode);
+  }
+}
+break;
+  case Stmt::CXXDefaultInitExprClass:
+if (auto *Init = dyn_cast(S)) {
+  if (Init->hasRewrittenInit()) {
+M[Init->getExpr()] = S;
+BuildParentMap(M, Init->getExpr(), OVMode);
+  }
+}
+break;
   default:
 for (Stmt *SubStmt : S->children()) {
   if (SubStmt) {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 64e6155de090c..2f3f3e92516ba 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -556,6 +556,8 @@ class CFGBuilder {
 
 private:
   // Visitors to walk an AST and construct the CFG.
+  CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice 
asc);
+  CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice 
asc);
   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed);
 
 case Stmt::CXXDefaultArgExprClass:
+  return VisitCXXDefaultArgExpr(cast(S), asc);
+
 case Stmt::CXXDefaultInitExprClass:
-  // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
-  // called function's declaration, not by the caller. If we simply add
-  // this expression to the CFG, we could end up with the same Expr
-  // appearing multiple times (PR13385).
-  //
-  // It's likewise possible for multiple CXXDefaultInitExprs for the same
-  // expression to be used in the same function (through aggregate
-  // initialization).
-  return VisitStmt(S, asc);
+  return VisitCXXDefaultInitExpr(cast(S), asc);
 
 case Stmt::CXXBindTemporaryExprClass:
   return VisitCXXBindTemporaryExpr(cast(S), asc);
@@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
+ AddStmtChoice asc) {
+  if (Arg->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Arg)) {
+  autoCreateBlock();
+  appendStmt(Block, Arg);
+}
+return VisitStmt(Arg->getExpr(), asc);
+  }
+  return VisitStmt(Arg, asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
+  AddStmtChoice asc) {
+  if (Init->hasRewrittenInit()) {
+if (asc.alwaysAdd(*this, Init)) {
+  autoCreateBlock();
+  appendStmt(Block, Init);
+}
+return VisitStmt(Init->getExpr(), asc);
+  }
+  return VisitStmt(Init, asc);
+}
+
 CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, ILE)) {
 autoCreateBlock();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0b1edf3e5c96b..41cb4293a8451 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 case Stmt::CXXDefaultArgExprClass:
 case Stmt::CXXDefaultInitExprClass: {
   Bldr.takeNodes(Pred);
-  ExplodedNodeSet PreVisit;
-  getCheckerManager().runCheckers