[clang] [clang][test] Avoid writing to a potentially write-protected dir (PR #88258)

2024-04-10 Thread Dmitri Gribenko via cfe-commits

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


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


[clang] 5906b1a - [APINotes][test] Fix permissions of a file copied from a source tree

2024-03-28 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2024-03-29T00:38:11+01:00
New Revision: 5906b1ad3f70586c72293d5c62eb3f26977b8b96

URL: 
https://github.com/llvm/llvm-project/commit/5906b1ad3f70586c72293d5c62eb3f26977b8b96
DIFF: 
https://github.com/llvm/llvm-project/commit/5906b1ad3f70586c72293d5c62eb3f26977b8b96.diff

LOG: [APINotes][test] Fix permissions of a file copied from a source tree

Our CI system makes the source tree read-only. The 'cp' command that
copies a directory from the source tree into a temp directory preserves
permissions, and the copied files stay read-only. When the test tries to
append to one of these files, it fails with a "permission denied" error.

Added: 


Modified: 
clang/test/APINotes/module-cache.m

Removed: 




diff  --git a/clang/test/APINotes/module-cache.m 
b/clang/test/APINotes/module-cache.m
index 5dcaf1181f9dcf..e5920884ad860f 100644
--- a/clang/test/APINotes/module-cache.m
+++ b/clang/test/APINotes/module-cache.m
@@ -27,6 +27,7 @@
 // RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log
 
 // Change the API notes file, after the module has rebuilt once.
+// RUN: chmod u+w %t/APINotes/SomeOtherKit.apinotes
 // RUN: echo '  - Selector: "methodA"' >> %t/APINotes/SomeOtherKit.apinotes
 // RUN: echo 'MethodKind: Instance' >> 
%t/APINotes/SomeOtherKit.apinotes
 // RUN: echo 'Availability: none' >> %t/APINotes/SomeOtherKit.apinotes



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


[clang] 219511a - [APINotes] Make an assert in a std::sort call tolerate self-comparisons

2024-03-28 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2024-03-28T23:11:58+01:00
New Revision: 219511aee21cc652e1ede0458de4a4a66f04c81c

URL: 
https://github.com/llvm/llvm-project/commit/219511aee21cc652e1ede0458de4a4a66f04c81c
DIFF: 
https://github.com/llvm/llvm-project/commit/219511aee21cc652e1ede0458de4a4a66f04c81c.diff

LOG: [APINotes] Make an assert in a std::sort call tolerate self-comparisons

libc++ debug mode verifies that a comparator passed to std::sort defines
a strict weak order by calling it with the same element.

See also:

- RFC that introduced the feature:
  
https://discourse.llvm.org/t/rfc-strict-weak-ordering-checks-in-the-debug-libc/70217

- `strict_weak_ordering_check.h` in libc++ sources.

Added: 


Modified: 
clang/lib/APINotes/APINotesWriter.cpp

Removed: 




diff  --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 76fd24ccfae984..e3f5d102fcd07f 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -441,7 +441,7 @@ void emitVersionedInfo(
   std::sort(VI.begin(), VI.end(),
 [](const std::pair ,
const std::pair ) -> bool {
-  assert(LHS.first != RHS.first &&
+  assert(( ==  || LHS.first != RHS.first) &&
  "two entries for the same version");
   return LHS.first < RHS.first;
 });



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


[clang] [clang][nullability] allow _Nonnull etc on nullable class types (PR #82705)

2024-03-07 Thread Dmitri Gribenko via cfe-commits


@@ -96,8 +146,16 @@ void AssignAndInitNonNullFromFn() {
   void *_Nonnull nonnull;
   nonnull = ReturnNullable(); // expected-warning{{implicit conversion from 
nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * 
_Nonnull'}}
   nonnull = {ReturnNullable()}; // expected-warning{{implicit conversion from 
nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * 
_Nonnull'}}
-
   TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from 
nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * 
_Nonnull}}
+
+  SmartPtr _Nonnull s(ReturnSmartNullable()); // expected-warning{{implicit 
conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer 
type 'SmartPtr _Nonnull'}}
+  SmartPtr _Nonnull s2{ReturnSmartNullable()}; // expected-warning{{implicit 
conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer 
type 'SmartPtr _Nonnull'}}
+  SmartPtr _Nonnull s3 = {ReturnSmartNullable()}; // 
expected-warning{{implicit conversion from nullable pointer 'SmartPtr 
_Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}}
+  SmartPtr _Nonnull s4 = ReturnSmartNullable(); // expected-warning{{implicit 
conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer 
type 'SmartPtr _Nonnull'}}
+  SmartPtr _Nonnull s_nonnull;
+  s_nonnull = ReturnSmartNullable(); // expected-warning{{implicit conversion 
from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 
'SmartPtr _Nonnull'}}
+  s_nonnull = {ReturnSmartNullable()};
+  TakeSmartNonnull(ReturnSmartNullable()); //expected-warning{{implicit 
conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer 
type 'SmartPtr _Nonnull}}

gribozavr wrote:

```suggestion
  TakeSmartNonnull(ReturnSmartNullable()); // expected-warning{{implicit 
conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer 
type 'SmartPtr _Nonnull'}}
```

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits


@@ -0,0 +1,625 @@
+//===-- NullPointerAnalysisModel.cpp *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines a generic null-pointer analysis model, used for finding
+// pointer null-checks after the pointer has already been dereferenced.
+//
+// Only a limited set of operations are currently recognized. Notably, pointer
+// arithmetic, null-pointer assignments and _nullable/_nonnull attributes are
+// missing as of yet.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Models/NullPointerAnalysisModel.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+namespace {
+using namespace ast_matchers;
+
+constexpr char kCond[] = "condition";
+constexpr char kVar[] = "var";
+constexpr char kValue[] = "value";
+constexpr char kIsNonnull[] = "is-nonnull";
+constexpr char kIsNull[] = "is-null";
+
+enum class SatisfiabilityResult {
+  // Returned when the value was not initialized yet.
+  Nullptr,
+  // Special value that signals that the boolean value can be anything.
+  // It signals that the underlying formulas are too complex to be calculated
+  // efficiently.
+  Top,
+  // Equivalent to the literal True in the current environment.
+  True,
+  // Equivalent to the literal False in the current environment.
+  False,
+  // Both True and False values could be produced with an appropriate set of
+  // conditions.
+  Unknown
+};
+
+using SR = SatisfiabilityResult;
+
+// FIXME: These AST matchers should also be exported via the
+// NullPointerAnalysisModel class, for tests
+auto ptrToVar(llvm::StringRef VarName = kVar) {
+  return traverse(TK_IgnoreUnlessSpelledInSource,
+  declRefExpr(hasType(isAnyPointer())).bind(VarName));
+}
+
+auto derefMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  unaryOperator(hasOperatorName("*"), hasUnaryOperand(ptrToVar(;
+}
+
+auto arrowMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  memberExpr(allOf(isArrow(), hasObjectExpression(ptrToVar();
+}
+
+auto castExprMatcher() {
+  return castExpr(hasCastKind(CK_PointerToBoolean),
+  hasSourceExpression(ptrToVar()))
+  .bind(kCond);
+}
+
+auto nullptrMatcher() {
+  return castExpr(hasCastKind(CK_NullToPointer)).bind(kVar);
+}
+
+auto addressofMatcher() {
+  return unaryOperator(hasOperatorName("&")).bind(kVar);
+}
+
+auto functionCallMatcher() {
+  return callExpr(hasDeclaration(functionDecl(returns(isAnyPointer()
+  .bind(kVar);
+}
+
+auto assignMatcher() {
+  return binaryOperation(isAssignmentOperator(), hasLHS(ptrToVar()),
+ hasRHS(expr().bind(kValue)));
+}
+
+auto anyPointerMatcher() { return expr(hasType(isAnyPointer())).bind(kVar); }
+
+// Only computes simple comparisons against the literals True and False in the
+// environment. Faster, but produces many Unknown values.
+SatisfiabilityResult shallowComputeSatisfiability(BoolValue *Val,
+  const Environment ) {
+  if (!Val)
+return SR::Nullptr;
+
+  if (isa(Val))
+return SR::Top;
+
+  if (Val == (true))
+return SR::True;
+
+  if (Val == (false))
+return SR::False;
+
+  return SR::Unknown;
+}
+
+// Computes satisfiability by using the flow condition. Slower, but more
+// precise.
+SatisfiabilityResult computeSatisfiability(BoolValue *Val,
+   const Environment ) {
+  // Early return with the fast compute values.
+  if (SatisfiabilityResult ShallowResult =
+  shallowComputeSatisfiability(Val, Env);
+  ShallowResult != SR::Unknown) {
+return ShallowResult;
+  }
+
+  if (Env.proves(Val->formula()))
+return SR::True;
+
+  if (Env.proves(Env.arena().makeNot(Val->formula(
+return SR::False;
+
+  return SR::Unknown;
+}
+
+inline BoolValue (llvm::StringRef Name, Value ) {
+  return *cast(RootValue.getProperty(Name));
+}
+
+// Assigns initial pointer null- and nonnull-values to a given Value.
+void 

[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits


@@ -0,0 +1,625 @@
+//===-- NullPointerAnalysisModel.cpp *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines a generic null-pointer analysis model, used for finding
+// pointer null-checks after the pointer has already been dereferenced.
+//
+// Only a limited set of operations are currently recognized. Notably, pointer
+// arithmetic, null-pointer assignments and _nullable/_nonnull attributes are
+// missing as of yet.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Models/NullPointerAnalysisModel.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+namespace {
+using namespace ast_matchers;
+
+constexpr char kCond[] = "condition";
+constexpr char kVar[] = "var";
+constexpr char kValue[] = "value";
+constexpr char kIsNonnull[] = "is-nonnull";
+constexpr char kIsNull[] = "is-null";
+
+enum class SatisfiabilityResult {
+  // Returned when the value was not initialized yet.
+  Nullptr,
+  // Special value that signals that the boolean value can be anything.
+  // It signals that the underlying formulas are too complex to be calculated
+  // efficiently.
+  Top,
+  // Equivalent to the literal True in the current environment.
+  True,
+  // Equivalent to the literal False in the current environment.
+  False,
+  // Both True and False values could be produced with an appropriate set of
+  // conditions.
+  Unknown
+};
+
+using SR = SatisfiabilityResult;
+
+// FIXME: These AST matchers should also be exported via the
+// NullPointerAnalysisModel class, for tests
+auto ptrToVar(llvm::StringRef VarName = kVar) {
+  return traverse(TK_IgnoreUnlessSpelledInSource,
+  declRefExpr(hasType(isAnyPointer())).bind(VarName));
+}
+
+auto derefMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  unaryOperator(hasOperatorName("*"), hasUnaryOperand(ptrToVar(;
+}
+
+auto arrowMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  memberExpr(allOf(isArrow(), hasObjectExpression(ptrToVar();
+}
+
+auto castExprMatcher() {
+  return castExpr(hasCastKind(CK_PointerToBoolean),
+  hasSourceExpression(ptrToVar()))

gribozavr wrote:

Why limit the cast argument to a var? It shouldn't matter if the argument is a 
complex expression. As long as the framework models the value somehow (for 
example, one of the implicit casts that the core framework already models, like 
the lvalue to rvalue cast), the transfer function should not need to worry 
about how that ended up happening.

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits


@@ -0,0 +1,625 @@
+//===-- NullPointerAnalysisModel.cpp *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines a generic null-pointer analysis model, used for finding
+// pointer null-checks after the pointer has already been dereferenced.
+//
+// Only a limited set of operations are currently recognized. Notably, pointer
+// arithmetic, null-pointer assignments and _nullable/_nonnull attributes are
+// missing as of yet.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Models/NullPointerAnalysisModel.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+namespace {
+using namespace ast_matchers;
+
+constexpr char kCond[] = "condition";
+constexpr char kVar[] = "var";
+constexpr char kValue[] = "value";
+constexpr char kIsNonnull[] = "is-nonnull";
+constexpr char kIsNull[] = "is-null";
+
+enum class SatisfiabilityResult {
+  // Returned when the value was not initialized yet.
+  Nullptr,
+  // Special value that signals that the boolean value can be anything.
+  // It signals that the underlying formulas are too complex to be calculated
+  // efficiently.
+  Top,
+  // Equivalent to the literal True in the current environment.
+  True,
+  // Equivalent to the literal False in the current environment.
+  False,
+  // Both True and False values could be produced with an appropriate set of
+  // conditions.
+  Unknown
+};
+
+using SR = SatisfiabilityResult;
+
+// FIXME: These AST matchers should also be exported via the
+// NullPointerAnalysisModel class, for tests
+auto ptrToVar(llvm::StringRef VarName = kVar) {
+  return traverse(TK_IgnoreUnlessSpelledInSource,
+  declRefExpr(hasType(isAnyPointer())).bind(VarName));
+}
+
+auto derefMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  unaryOperator(hasOperatorName("*"), hasUnaryOperand(ptrToVar(;
+}
+
+auto arrowMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  memberExpr(allOf(isArrow(), hasObjectExpression(ptrToVar();
+}
+
+auto castExprMatcher() {
+  return castExpr(hasCastKind(CK_PointerToBoolean),
+  hasSourceExpression(ptrToVar()))
+  .bind(kCond);
+}
+
+auto nullptrMatcher() {
+  return castExpr(hasCastKind(CK_NullToPointer)).bind(kVar);
+}
+
+auto addressofMatcher() {
+  return unaryOperator(hasOperatorName("&")).bind(kVar);
+}
+
+auto functionCallMatcher() {
+  return callExpr(hasDeclaration(functionDecl(returns(isAnyPointer()
+  .bind(kVar);
+}
+
+auto assignMatcher() {
+  return binaryOperation(isAssignmentOperator(), hasLHS(ptrToVar()),
+ hasRHS(expr().bind(kValue)));
+}
+
+auto anyPointerMatcher() { return expr(hasType(isAnyPointer())).bind(kVar); }
+
+// Only computes simple comparisons against the literals True and False in the
+// environment. Faster, but produces many Unknown values.
+SatisfiabilityResult shallowComputeSatisfiability(BoolValue *Val,
+  const Environment ) {
+  if (!Val)
+return SR::Nullptr;
+
+  if (isa(Val))
+return SR::Top;
+
+  if (Val == (true))
+return SR::True;
+
+  if (Val == (false))
+return SR::False;
+
+  return SR::Unknown;
+}
+
+// Computes satisfiability by using the flow condition. Slower, but more
+// precise.
+SatisfiabilityResult computeSatisfiability(BoolValue *Val,
+   const Environment ) {
+  // Early return with the fast compute values.
+  if (SatisfiabilityResult ShallowResult =
+  shallowComputeSatisfiability(Val, Env);
+  ShallowResult != SR::Unknown) {
+return ShallowResult;
+  }
+
+  if (Env.proves(Val->formula()))
+return SR::True;
+
+  if (Env.proves(Env.arena().makeNot(Val->formula(
+return SR::False;
+
+  return SR::Unknown;
+}
+
+inline BoolValue (llvm::StringRef Name, Value ) {
+  return *cast(RootValue.getProperty(Name));
+}
+
+// Assigns initial pointer null- and nonnull-values to a given Value.
+void 

[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits


@@ -0,0 +1,625 @@
+//===-- NullPointerAnalysisModel.cpp *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines a generic null-pointer analysis model, used for finding
+// pointer null-checks after the pointer has already been dereferenced.
+//
+// Only a limited set of operations are currently recognized. Notably, pointer
+// arithmetic, null-pointer assignments and _nullable/_nonnull attributes are
+// missing as of yet.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Models/NullPointerAnalysisModel.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+namespace {
+using namespace ast_matchers;
+
+constexpr char kCond[] = "condition";
+constexpr char kVar[] = "var";
+constexpr char kValue[] = "value";
+constexpr char kIsNonnull[] = "is-nonnull";
+constexpr char kIsNull[] = "is-null";
+
+enum class SatisfiabilityResult {
+  // Returned when the value was not initialized yet.
+  Nullptr,
+  // Special value that signals that the boolean value can be anything.
+  // It signals that the underlying formulas are too complex to be calculated
+  // efficiently.
+  Top,
+  // Equivalent to the literal True in the current environment.
+  True,
+  // Equivalent to the literal False in the current environment.
+  False,
+  // Both True and False values could be produced with an appropriate set of
+  // conditions.
+  Unknown
+};
+
+using SR = SatisfiabilityResult;
+
+// FIXME: These AST matchers should also be exported via the
+// NullPointerAnalysisModel class, for tests
+auto ptrToVar(llvm::StringRef VarName = kVar) {
+  return traverse(TK_IgnoreUnlessSpelledInSource,
+  declRefExpr(hasType(isAnyPointer())).bind(VarName));
+}
+
+auto derefMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  unaryOperator(hasOperatorName("*"), hasUnaryOperand(ptrToVar(;
+}
+
+auto arrowMatcher() {
+  return traverse(
+  TK_IgnoreUnlessSpelledInSource,
+  memberExpr(allOf(isArrow(), hasObjectExpression(ptrToVar();
+}
+
+auto castExprMatcher() {
+  return castExpr(hasCastKind(CK_PointerToBoolean),
+  hasSourceExpression(ptrToVar()))
+  .bind(kCond);
+}
+
+auto nullptrMatcher() {
+  return castExpr(hasCastKind(CK_NullToPointer)).bind(kVar);
+}
+
+auto addressofMatcher() {
+  return unaryOperator(hasOperatorName("&")).bind(kVar);
+}
+
+auto functionCallMatcher() {
+  return callExpr(hasDeclaration(functionDecl(returns(isAnyPointer()
+  .bind(kVar);

gribozavr wrote:

Please see my other comment about following the `transferValue_Pointer` pattern 
from our nullability checker - if you do that you wouldn't need to define 
multiple matchers to cover all C++ syntax that could produce a pointer. Instead 
it would be only one matcher that covers all pointer-valued expressions, which 
should be simpler.

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits


@@ -0,0 +1,112 @@
+//===-- NullPointerAnalysisModel.h --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines a generic null-pointer analysis model, used for finding
+// pointer null-checks after the pointer has already been dereferenced.
+//
+// Only a limited set of operations are currently recognized. Notably, pointer
+// arithmetic, null-pointer assignments and _nullable/_nonnull attributes are
+// missing as of yet.
+//
+//===--===//
+
+#ifndef CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_NULLPOINTERANALYSISMODEL_H
+#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_NULLPOINTERANALYSISMODEL_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+class NullPointerAnalysisModel
+: public DataflowAnalysis {
+public:
+  /// A transparent wrapper around the function arguments of transferBranch().
+  /// Does not outlive the call to transferBranch().
+  struct TransferArgs {
+bool Branch;
+Environment 
+  };
+
+private:
+  CFGMatchSwitch TransferMatchSwitch;
+  ASTMatchSwitch BranchTransferMatchSwitch;
+
+public:
+  explicit NullPointerAnalysisModel(ASTContext );
+
+  static NoopLattice initialElement() { return {}; }
+
+  static ast_matchers::StatementMatcher ptrValueMatcher();
+
+  // Used to initialize the storage locations of function arguments.
+  // Required to merge these values within the environment.
+  void initializeFunctionParameters(const ControlFlowContext ,
+Environment );
+
+  void transfer(const CFGElement , NoopLattice , Environment );
+
+  void transferBranch(bool Branch, const Stmt *E, NoopLattice ,
+  Environment );
+
+  void join(QualType Type, const Value , const Environment ,
+const Value , const Environment , Value ,
+Environment ) override;
+
+  ComparisonResult compare(QualType Type, const Value ,
+   const Environment , const Value ,
+   const Environment ) override;
+
+  Value *widen(QualType Type, Value , const Environment ,
+   Value , Environment ) override;
+};
+
+class NullCheckAfterDereferenceDiagnoser {
+public:
+  struct DiagnoseArgs {
+llvm::DenseMap 
+llvm::DenseMap 
+const Environment 
+  };
+
+  using ResultType =
+  std::pair, std::vector>;

gribozavr wrote:

Could you add a doc comment that explains what these vectors hold?

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


[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)

2024-03-06 Thread Dmitri Gribenko via cfe-commits


@@ -0,0 +1,625 @@
+//===-- NullPointerAnalysisModel.cpp *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines a generic null-pointer analysis model, used for finding
+// pointer null-checks after the pointer has already been dereferenced.
+//
+// Only a limited set of operations are currently recognized. Notably, pointer
+// arithmetic, null-pointer assignments and _nullable/_nonnull attributes are
+// missing as of yet.
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Models/NullPointerAnalysisModel.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+namespace {
+using namespace ast_matchers;
+
+constexpr char kCond[] = "condition";
+constexpr char kVar[] = "var";
+constexpr char kValue[] = "value";
+constexpr char kIsNonnull[] = "is-nonnull";
+constexpr char kIsNull[] = "is-null";
+
+enum class SatisfiabilityResult {
+  // Returned when the value was not initialized yet.
+  Nullptr,
+  // Special value that signals that the boolean value can be anything.
+  // It signals that the underlying formulas are too complex to be calculated
+  // efficiently.
+  Top,
+  // Equivalent to the literal True in the current environment.
+  True,
+  // Equivalent to the literal False in the current environment.
+  False,
+  // Both True and False values could be produced with an appropriate set of
+  // conditions.
+  Unknown
+};
+
+using SR = SatisfiabilityResult;
+
+// FIXME: These AST matchers should also be exported via the
+// NullPointerAnalysisModel class, for tests
+auto ptrToVar(llvm::StringRef VarName = kVar) {
+  return traverse(TK_IgnoreUnlessSpelledInSource,

gribozavr wrote:

Could you check if `TK_IgnoreUnlessSpelledInSource` is necessary here? 
Generally it shouldn't be. The dataflow framework applies the transfer function 
to each CFG element. So it will visit both the implicit wrapping AST nodes and 
the nested explicitly spelled node.

Furthermore, applying the transfer function twice to effectively the same 
construct could lead to bad effects and incorrect state updates (if the author 
of the analysis does not carefully consider that this is a possibility).

This is why we think that the best practice for writing AST matchers for the 
transfer function is to only match the immediate node being visited by the 
dataflow framework right now, don't traverse into the expression tree.

If there is an issue related to implicit AST nodes not propagating the state, 
we should look at it more carefully, and probably either enhance the framework 
core to do that, or add transfer functions for the specific AST nodes to 
propagate the necessary state.

PTAL at `VisitImplicitCastExpr` in 
llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp - the core framework 
tries to forward all of the already-modeled values through implicit casts that 
can be modeled generically.

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


[clang] [clang][dataflow] Add new `join` API and replace existing `merge` implementations. (PR #80361)

2024-02-01 Thread Dmitri Gribenko via cfe-commits


@@ -105,6 +105,27 @@ class Environment {
   return true;
 }
 
+/// Modifies `JoinedVal` to approximate both `Val1` and `Val2`. This should
+/// obey the properties of a lattice join.
+///
+/// `Env1` and `Env2` can be used to query child values and path condition
+/// implications of `Val1` and `Val2` respectively.
+///
+/// Requirements:
+///
+///  `Val1` and `Val2` must be distinct.
+///
+///  `Val1`, `Val2`, and `JoinedVal` must model values of type `Type`.
+///
+///  `Val1` and `Val2` must be assigned to the same storage location in
+///  `Env1` and `Env2` respectively.
+virtual void join(QualType Type, const Value , const Environment 
,
+  const Value , const Environment ,
+  Value , Environment ) {
+  assert(merge(Type, Val1, Env1, Val2, Env2, JoinedVal, JoinedEnv) &&
+ "dropping merged value is unsupported");

gribozavr wrote:

```suggestion
  bool ShouldKeep = merge(Type, Val1, Env1, Val2, Env2, JoinedVal, 
JoinedEnv);
  assert(ShouldKeep && "dropping merged value is unsupported");
  (void)ShouldKeep;
```

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


[clang] [Clang][AST] Fix a crash on attaching doc comments (PR #78716)

2024-01-20 Thread Dmitri Gribenko via cfe-commits

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


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


[clang] [Clang][AST] Fix a crash on attaching doc comments (PR #78716)

2024-01-20 Thread Dmitri Gribenko via cfe-commits

gribozavr wrote:

Thank you for the fix.

Here's what happens here.

This function receives the just-parsed decls, and its aim is to the comment in 
the same vicinity (I know this because I am the original author of the code).

This first loop over `Decls` identifies the file in which we will be looking 
for comments. Then the code retrieves the comments in that file (`auto 
CommentsInThisFile = Comments.getCommentsInFile(File);`). At this point we have 
really committed which file we are looking in.

Now, the next loop over `Decls` disturbs this decision this by adjusting the 
decl to the template. That decl could be in a different file.

The call `const auto DeclLocs = getDeclLocsForCommentSearch(D, SourceMgr);` 
retrieves source locations for the adjusted decl. The adjusted decl could be in 
a different file from the comments that we retrieved in `CommentsInThisFile`.

Next, we are passing the mismatched `DeclLocs` and `CommentsInThisFile` into 
`getRawCommentForDeclNoCacheImpl`, which crashes when they come from different 
files.

I think the bug was introduced as a consequence of f31d8df1c8c69 and 
b67d3702577d4, while the recent source location change merely unmasked it.

So, this makes me wondering if there is a better way to structure this code to 
make the mismatch between `DeclLocs` and `CommentsInThisFile` impossible. I 
think a better way would be to merge the two loops over `Decls` and call 
`Comments.getCommentsInFile` for the source location from `DeclLocs`.

WDYT @chenshanzhi ? We can merge this change as is, since it is a good crash 
fix, but it would be great if you could make the code more robust by merging 
the loops.

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


[clang] [clang][dataflow] Disallow setting properties on `RecordValue`s. (PR #76042)

2023-12-21 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang][dataflow] Disallow setting properties on `RecordValue`s. (PR #76042)

2023-12-21 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang][dataflow] Disallow setting properties on `RecordValue`s. (PR #76042)

2023-12-21 Thread Dmitri Gribenko via cfe-commits

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


[clang] [clang][dataflow] Disallow setting properties on `RecordValue`s. (PR #76042)

2023-12-21 Thread Dmitri Gribenko via cfe-commits


@@ -636,40 +636,37 @@ class OptionalIntAnalysis final
 if (!CS)
   return;
 const Stmt *S = CS->getStmt();
-auto OptionalIntRecordDecl = recordDecl(hasName("OptionalInt"));
-auto HasOptionalIntType = hasType(OptionalIntRecordDecl);
-
-SmallVector Matches = match(
-stmt(anyOf(cxxConstructExpr(HasOptionalIntType).bind("construct"),
-   cxxOperatorCallExpr(
-   callee(cxxMethodDecl(ofClass(OptionalIntRecordDecl
-   .bind("operator"))),
-*S, getASTContext());
-if (const auto *E = selectFirst(
-"construct", Matches)) {
-  cast(Env.getValue(*E))
-  ->setProperty("has_value", Env.getBoolLiteralValue(false));
-} else if (const auto *E =
-   selectFirst("operator", Matches)) {
-  assert(E->getNumArgs() > 0);
-  auto *Object = E->getArg(0);
-  assert(Object != nullptr);
-
-  refreshRecordValue(*Object, Env)
-  .setProperty("has_value", Env.getBoolLiteralValue(true));
+const Expr *E = dyn_cast(S);
+if (!E)
+  return;
+
+if (!E->getType()->isPointerType())
+  return;
+
+// Make sure we have a `PointerValue` for `E`.
+auto *PtrVal = cast_or_null(Env.getValue(*E));

gribozavr wrote:

There are a lot of things that a poorly-written check could do, so is this the 
one to spend our time protecting against? Maybe. I wish the framework helped 
more with convergence. Convergence issues are indeed difficult, and we 
ourselves have fully solved the problem and haven't found a good tradeoff re: 
convergence for nullability. As we deploy this check internally, I expect us to 
tweak things in this area, hopefully we will get a better understanding, or 
even ideas for framework-level features. There is also non-trivial work we 
already know needs to be done that is convergence-related, like a generic "Top" 
value.

So I think at this point I'd prefer to keep the extensibility with sharp edges, 
rather than reduce expressivity.

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


[clang] [CUDA] work around more __noinline__ conflicts with libc++ (PR #74123)

2023-12-01 Thread Dmitri Gribenko via cfe-commits

gribozavr wrote:

I don't mind this, but should libc++ start using `_LIBCPP_NOINLINE`, we would 
be playing a catch-up game here.

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


[clang] b9b627f - [clang] Fix a new test to not write temp files to the git repository

2023-11-27 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-11-27T18:04:49+01:00
New Revision: b9b627fbc3bc64cd3e7e009917df35d2971827d9

URL: 
https://github.com/llvm/llvm-project/commit/b9b627fbc3bc64cd3e7e009917df35d2971827d9
DIFF: 
https://github.com/llvm/llvm-project/commit/b9b627fbc3bc64cd3e7e009917df35d2971827d9.diff

LOG: [clang] Fix a new test to not write temp files to the git repository

Added: 


Modified: 
clang/test/OpenMP/dispatch_unsupported.c

Removed: 




diff  --git a/clang/test/OpenMP/dispatch_unsupported.c 
b/clang/test/OpenMP/dispatch_unsupported.c
index 92f555e4b414f4e..fe7ccfa90a5831a 100644
--- a/clang/test/OpenMP/dispatch_unsupported.c
+++ b/clang/test/OpenMP/dispatch_unsupported.c
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -emit-llvm -fopenmp -disable-llvm-passes %s -verify=expected
+// RUN: %clang_cc1 -emit-llvm -fopenmp -disable-llvm-passes %s -o /dev/null 
-verify=expected
 
-// expected-error@+2 {{cannot compile this OpenMP dispatch directive yet}} 
+// expected-error@+2 {{cannot compile this OpenMP dispatch directive yet}}
 void a(){
 #pragma omp dispatch
 a();



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


[clang] e94e790 - [clang][test] Don't write temporary (actually, unused) outputs into CWD

2023-09-08 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-09-08T23:54:41+02:00
New Revision: e94e790e46d0afd073b706afa0cf91804e7826e0

URL: 
https://github.com/llvm/llvm-project/commit/e94e790e46d0afd073b706afa0cf91804e7826e0
DIFF: 
https://github.com/llvm/llvm-project/commit/e94e790e46d0afd073b706afa0cf91804e7826e0.diff

LOG: [clang][test] Don't write temporary (actually, unused) outputs into CWD

Added: 


Modified: 
clang/test/CodeGen/X86/avx512-error.c

Removed: 




diff  --git a/clang/test/CodeGen/X86/avx512-error.c 
b/clang/test/CodeGen/X86/avx512-error.c
index 1642527f292828e..8e42105ec112726 100644
--- a/clang/test/CodeGen/X86/avx512-error.c
+++ b/clang/test/CodeGen/X86/avx512-error.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown 
-target-feature +avx512bw -target-feature -evex512 -emit-llvm -verify 
-DFEATURE_TEST=1
-// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown 
-target-feature +avx512bw -target-feature -evex512 -emit-llvm -verify 
-DFEATURE_TEST=2
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown 
-target-feature +avx512bw -target-feature -evex512 -emit-llvm -o /dev/null 
-verify -DFEATURE_TEST=1
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown 
-target-feature +avx512bw -target-feature -evex512 -emit-llvm -o /dev/null 
-verify -DFEATURE_TEST=2
 
 #include 
 



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


[clang] d64c363 - [Clang][LoongArch] Add '-o /dev/null' to a test that does not care about the output

2023-08-09 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-08-09T16:07:41+02:00
New Revision: d64c363f35b98ab9750a3c3a5828d8df011a4a45

URL: 
https://github.com/llvm/llvm-project/commit/d64c363f35b98ab9750a3c3a5828d8df011a4a45
DIFF: 
https://github.com/llvm/llvm-project/commit/d64c363f35b98ab9750a3c3a5828d8df011a4a45.diff

LOG: [Clang][LoongArch] Add '-o /dev/null' to a test that does not care about 
the output

Tests should not write to the CWD because it might not be writeable.
Either use %t, or /dev/null if the test does not check the output.

Added: 


Modified: 
clang/test/CodeGen/LoongArch/intrinsic-la32-error.c

Removed: 




diff  --git a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c 
b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
index db113a13eb5a95..026a2db0088920 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple loongarch32 -emit-llvm -S -verify %s -o /dev/null
-// RUN: not %clang_cc1 -triple loongarch32 -DFEATURE_CHECK -emit-llvm %s 2>&1 \
+// RUN: not %clang_cc1 -triple loongarch32 -DFEATURE_CHECK -emit-llvm %s -o 
/dev/null 2>&1 \
 // RUN:   | FileCheck %s
 
 #include 



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


[clang] bddaa35 - Anonymous unions should be transparent wrt `[[clang::trivial_abi]]`.

2023-08-07 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-08-07T20:30:48+02:00
New Revision: bddaa35177861545fc329123e55b6a3b34549507

URL: 
https://github.com/llvm/llvm-project/commit/bddaa35177861545fc329123e55b6a3b34549507
DIFF: 
https://github.com/llvm/llvm-project/commit/bddaa35177861545fc329123e55b6a3b34549507.diff

LOG: Anonymous unions should be transparent wrt `[[clang::trivial_abi]]`.

Anonymous unions should be transparent wrt `[[clang::trivial_abi]]`.

Consider the test input below:

 ```
 struct [[clang::trivial_abi]] Trivial {
   Trivial() {}
   Trivial(Trivial&& other) {}
   Trivial& operator=(Trivial&& other) { return *this; }
   ~Trivial() {}
 };
 static_assert(__is_trivially_relocatable(Trivial), "");

 struct [[clang::trivial_abi]] S2 {
   S2(S2&& other) {}
   S2& operator=(S2&& other) { return *this; }
   ~S2() {}
   union { Trivial field; };
 };
 static_assert(__is_trivially_relocatable(S2), "");
 ```

Before the fix Clang would warn that 'trivial_abi' is disallowed on 'S2'
because it has a field of a non-trivial class type (the type of the
anonymous union is non-trivial, because it doesn't have the
`[[clang::trivial_abi]]` attribute applied to it).  Consequently, before
the fix the `static_assert` about `__is_trivially_relocatable` would
fail.

Note that `[[clang::trivial_abi]]` cannot be applied to the anonymous
union, because Clang warns that 'trivial_abi' is disallowed on '(unnamed
union at ...)' because its copy constructors and move constructors are
all deleted. Also note that it is impossible to provide copy nor move
constructors for anonymous unions and structs.

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D155895

Added: 


Modified: 
clang/include/clang/Basic/LangOptions.h
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaCXX/attr-trivial-abi.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 3ef68ca8af6685..d926cfcd4d8665 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -230,6 +230,12 @@ class LangOptions : public LangOptionsBase {
 ///   - consider classes with defaulted special member functions non-pod.
 Ver15,
 
+/// Attempt to be ABI-compatible with code generated by Clang 17.0.x.
+/// This causes clang to:
+///   - Treat `[[clang::trivial_abi]]` as ill-formed and ignore it if any
+/// field is an anonymous union and/or struct.
+Ver17,
+
 /// Conform to the underlying platform's C and C++ ABIs as closely
 /// as we can.
 Latest

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index be53ce3e472659..699b315269deb3 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3474,6 +3474,8 @@ void CompilerInvocation::GenerateLangArgs(const 
LangOptions ,
 GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0");
   else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver15)
 GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0");
+  else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver17)
+GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
 
   if (Opts.getSignReturnAddressScope() ==
   LangOptions::SignReturnAddressScopeKind::All)
@@ -3959,6 +3961,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions , 
ArgList ,
 Opts.setClangABICompat(LangOptions::ClangABI::Ver14);
   else if (Major <= 15)
 Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
+  else if (Major <= 17)
+Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
 } else if (Ver != "latest") {
   Diags.Report(diag::err_drv_invalid_value)
   << A->getAsString(Args) << A->getValue();

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 2c2c9dc8147437..6c29efc03a4b78 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -45,6 +45,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include 
@@ -10413,21 +10414,35 @@ void 
Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl ) {
 }
   }
 
-  for (const auto *FD : RD.fields()) {
-// Ill-formed if the field is an ObjectiveC pointer or of a type that is
-// non-trivial for the purpose of calls.
+  llvm::SmallVector FieldsToCheck{RD.fields()};
+  while (!FieldsToCheck.empty()) {
+const FieldDecl *FD = FieldsToCheck.pop_back_val();
+
+// Ill-formed if the field is an ObjectiveC pointer.
 QualType FT = FD->getType();
 if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
   PrintDiagAndRemoveAttr(4);
   return;
 }
 

[clang-tools-extra] c0abd38 - [clang-tidy] Remove 'const' qualifiers on return types that do nothing

2023-08-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-08-07T02:55:03+02:00
New Revision: c0abd3814564a568dfc607c216e6407eaa314f46

URL: 
https://github.com/llvm/llvm-project/commit/c0abd3814564a568dfc607c216e6407eaa314f46
DIFF: 
https://github.com/llvm/llvm-project/commit/c0abd3814564a568dfc607c216e6407eaa314f46.diff

LOG: [clang-tidy] Remove 'const' qualifiers on return types that do nothing

Added: 


Modified: 
clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index dc3b0f70fb8add..c43d46b145a178 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -78,18 +78,18 @@ static const llvm::StringSet<> StdNames{
 "std::begin", "std::cbegin", "std::rbegin", "std::crbegin", "std::end",
 "std::cend",  "std::rend",   "std::crend",  "std::size"};
 
-static const StatementMatcher integerComparisonMatcher() {
+static StatementMatcher integerComparisonMatcher() {
   return expr(ignoringParenImpCasts(
   declRefExpr(to(varDecl(equalsBoundNode(InitVarName));
 }
 
-static const DeclarationMatcher initToZeroMatcher() {
+static DeclarationMatcher initToZeroMatcher() {
   return varDecl(
  hasInitializer(ignoringParenImpCasts(integerLiteral(equals(0)
   .bind(InitVarName);
 }
 
-static const StatementMatcher incrementVarMatcher() {
+static StatementMatcher incrementVarMatcher() {
   return declRefExpr(to(varDecl(equalsBoundNode(InitVarName;
 }
 



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


[clang] 3b29b8a - Expose DataflowAnalysisContext.querySolver().

2023-06-30 Thread Dmitri Gribenko via cfe-commits

Author: Samira Bazuzi
Date: 2023-07-01T00:15:45+02:00
New Revision: 3b29b8a2aba205b59163ba11c537fbfe25133181

URL: 
https://github.com/llvm/llvm-project/commit/3b29b8a2aba205b59163ba11c537fbfe25133181
DIFF: 
https://github.com/llvm/llvm-project/commit/3b29b8a2aba205b59163ba11c537fbfe25133181.diff

LOG: Expose DataflowAnalysisContext.querySolver().

This allows for use of the same solver used by the DAC for additional solving 
post-analysis and thus shared use of MaxIterations in WatchedLiteralsSolver.

Reviewed By: ymandel, gribozavr2, sammccall

Differential Revision: https://reviews.llvm.org/D153805

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index eba42fc3418f68..735f2b2d85021c 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -175,6 +175,14 @@ class DataflowAnalysisContext {
 
   Arena () { return *A; }
 
+  /// Returns the outcome of satisfiability checking on `Constraints`.
+  ///
+  /// Flow conditions are not incorporated, so they may need to be manually
+  /// included in `Constraints` to provide contextually-accurate results, e.g.
+  /// if any definitions or relationships of the values in `Constraints` have
+  /// been stored in flow conditions.
+  Solver::Result querySolver(llvm::SetVector Constraints);
+
 private:
   friend class Environment;
 
@@ -204,13 +212,6 @@ class DataflowAnalysisContext {
   AtomicBoolValue , llvm::SetVector ,
   llvm::DenseSet );
 
-  /// Returns the outcome of satisfiability checking on `Constraints`.
-  /// Possible outcomes are:
-  /// - `Satisfiable`: A satisfying assignment exists and is returned.
-  /// - `Unsatisfiable`: A satisfying assignment does not exist.
-  /// - `TimedOut`: The search for a satisfying assignment was not completed.
-  Solver::Result querySolver(llvm::SetVector Constraints);
-
   /// Returns true if the solver is able to prove that there is no satisfying
   /// assignment for `Constraints`
   bool isUnsatisfiable(llvm::SetVector Constraints) {



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


[clang] 7ebf64f - [clang][analyzer][NFC] Use the operator new directly with the `BumpPtrAllocator`

2023-05-31 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-05-31T20:18:30+02:00
New Revision: 7ebf64f7e934a5e42d550194604b613113132bc0

URL: 
https://github.com/llvm/llvm-project/commit/7ebf64f7e934a5e42d550194604b613113132bc0
DIFF: 
https://github.com/llvm/llvm-project/commit/7ebf64f7e934a5e42d550194604b613113132bc0.diff

LOG: [clang][analyzer][NFC] Use the operator new directly with the 
`BumpPtrAllocator`

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D151818

Added: 


Modified: 
clang/lib/Analysis/CFG.cpp
clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
clang/lib/StaticAnalyzer/Core/MemRegion.cpp
clang/lib/StaticAnalyzer/Core/SymbolManager.cpp

Removed: 




diff  --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 4c8ceb792d2a7..246bace4debcf 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1992,8 +1992,7 @@ LocalScope* 
CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
   if (Scope)
 return Scope;
   llvm::BumpPtrAllocator  = cfg->getAllocator();
-  return new (alloc.Allocate())
-  LocalScope(BumpVectorContext(alloc), ScopePos);
+  return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);
 }
 
 /// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
@@ -5214,8 +5213,7 @@ CFGBlock *CFG::createBlock() {
   bool first_block = begin() == end();
 
   // Create the block.
-  CFGBlock *Mem = getAllocator().Allocate();
-  new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this);
+  CFGBlock *Mem = new (getAllocator()) CFGBlock(NumBlockIDs++, BlkBVC, this);
   Blocks.push_back(Mem, BlkBVC);
 
   // If this is the first block, set it as the Entry and Exit.

diff  --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp 
b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index 5a5851975bb60..5924f6a671c2a 100644
--- a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -97,8 +97,7 @@ const llvm::APSInt& BasicValueFactory::getValue(const 
llvm::APSInt& X) {
   FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!P) {
-P = BPAlloc.Allocate();
-new (P) FoldNodeTy(X);
+P = new (BPAlloc) FoldNodeTy(X);
 APSIntSet.InsertNode(P, InsertPos);
   }
 
@@ -132,8 +131,7 @@ BasicValueFactory::getCompoundValData(QualType T,
   CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!D) {
-D = BPAlloc.Allocate();
-new (D) CompoundValData(T, Vals);
+D = new (BPAlloc) CompoundValData(T, Vals);
 CompoundValDataSet.InsertNode(D, InsertPos);
   }
 
@@ -151,8 +149,7 @@ BasicValueFactory::getLazyCompoundValData(const StoreRef 
,
 LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!D) {
-D = BPAlloc.Allocate();
-new (D) LazyCompoundValData(store, region);
+D = new (BPAlloc) LazyCompoundValData(store, region);
 LazyCompoundValDataSet.InsertNode(D, InsertPos);
   }
 
@@ -169,8 +166,7 @@ const PointerToMemberData 
*BasicValueFactory::getPointerToMemberData(
   PointerToMemberDataSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!D) {
-D = BPAlloc.Allocate();
-new (D) PointerToMemberData(ND, L);
+D = new (BPAlloc) PointerToMemberData(ND, L);
 PointerToMemberDataSet.InsertNode(D, InsertPos);
   }
 
@@ -358,8 +354,7 @@ BasicValueFactory::getPersistentSValWithData(const SVal& V, 
uintptr_t Data) {
   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!P) {
-P = BPAlloc.Allocate();
-new (P) FoldNodeTy(std::make_pair(V, Data));
+P = new (BPAlloc) FoldNodeTy(std::make_pair(V, Data));
 Map.InsertNode(P, InsertPos);
   }
 
@@ -383,8 +378,7 @@ BasicValueFactory::getPersistentSValPair(const SVal& V1, 
const SVal& V2) {
   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!P) {
-P = BPAlloc.Allocate();
-new (P) FoldNodeTy(std::make_pair(V1, V2));
+P = new (BPAlloc) FoldNodeTy(std::make_pair(V1, V2));
 Map.InsertNode(P, InsertPos);
   }
 

diff  --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 314a4feda81b3..e1f26a50cbc5e 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -233,8 +233,7 @@ void ExplodedNode::NodeGroup::addNode(ExplodedNode *N, 
ExplodedGraph ) {
 ExplodedNode *Old = Storage.get();
 
 BumpVectorContext  = G.getNodeAllocator();
-V = G.getAllocator().Allocate();
-new (V) ExplodedNodeVector(Ctx, 4);
+V = new (G.getAllocator()) ExplodedNodeVector(Ctx, 4);
 V->push_back(Old, Ctx);
 
 Storage = V;

diff  --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp 
b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index d7409ae6aebe8..7cda64d6a028a 100644
--- 

[clang] 8a40f89 - [clang][analyzer][NFC] Replace dyn_cast with cast in MemRegion::getMemorySpace

2023-05-30 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-05-30T18:30:30+02:00
New Revision: 8a40f89e2e9357539db0f9a119db0fcfc77232ab

URL: 
https://github.com/llvm/llvm-project/commit/8a40f89e2e9357539db0f9a119db0fcfc77232ab
DIFF: 
https://github.com/llvm/llvm-project/commit/8a40f89e2e9357539db0f9a119db0fcfc77232ab.diff

LOG: [clang][analyzer][NFC] Replace dyn_cast with cast in 
MemRegion::getMemorySpace

MemRegion::getMemorySpace() is annotated with
LLVM_ATTRIBUTE_RETURNS_NONNULL (which triggers instant UB if a null
pointer is returned), and callers indeed don't check the return value
for null. Thus, even though llvm::dyn_cast is called, it can never
return null in this context. Therefore, we can safely call llvm::cast.

Reviewed By: steakhal

Differential Revision: https://reviews.llvm.org/D151727

Added: 


Modified: 
clang/lib/StaticAnalyzer/Core/MemRegion.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp 
b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index bb45a879471a..d7409ae6aebe 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1279,7 +1279,7 @@ const MemSpaceRegion *MemRegion::getMemorySpace() const {
 SR = dyn_cast(R);
   }
 
-  return dyn_cast(R);
+  return cast(R);
 }
 
 bool MemRegion::hasStackStorage() const {



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


[clang] 0989ce9 - [clang][analyzer][NFC] Move dyn_cast's into if statements for readability

2023-05-30 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-05-30T18:22:43+02:00
New Revision: 0989ce947e3dd64f3e29e7c34f186c0a23c0323d

URL: 
https://github.com/llvm/llvm-project/commit/0989ce947e3dd64f3e29e7c34f186c0a23c0323d
DIFF: 
https://github.com/llvm/llvm-project/commit/0989ce947e3dd64f3e29e7c34f186c0a23c0323d.diff

LOG: [clang][analyzer][NFC] Move dyn_cast's into if statements for readability

Reviewed By: steakhal

Differential Revision: https://reviews.llvm.org/D151725

Added: 


Modified: 
clang/lib/StaticAnalyzer/Core/MemRegion.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp 
b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 0c126a632f74..bb45a879471a 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -712,21 +712,17 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) 
const {
 }
 
 SourceRange MemRegion::sourceRange() const {
-  const auto *const VR = dyn_cast(this->getBaseRegion());
-  const auto *const FR = dyn_cast(this);
-
   // Check for more specific regions first.
-  // FieldRegion
-  if (FR) {
+  if (auto *FR = dyn_cast(this)) {
 return FR->getDecl()->getSourceRange();
   }
-  // VarRegion
-  else if (VR) {
+
+  if (auto *VR = dyn_cast(this->getBaseRegion())) {
 return VR->getDecl()->getSourceRange();
   }
+
   // Return invalid source range (can be checked by client).
-  else
-return {};
+  return {};
 }
 
 
//===--===//



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


[clang] daa95c7 - [clang][analyzer][NFC] Remove unnecessary FALLTHROUGH markers

2023-05-30 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-05-30T18:16:35+02:00
New Revision: daa95c7de5b7d004bd6c48f5099b7b88f1f5d16d

URL: 
https://github.com/llvm/llvm-project/commit/daa95c7de5b7d004bd6c48f5099b7b88f1f5d16d
DIFF: 
https://github.com/llvm/llvm-project/commit/daa95c7de5b7d004bd6c48f5099b7b88f1f5d16d.diff

LOG: [clang][analyzer][NFC] Remove unnecessary FALLTHROUGH markers

They are redundant with the [[fallthrough]]; attribute that follows.

Reviewed By: steakhal

Differential Revision: https://reviews.llvm.org/D151723

Added: 


Modified: 
clang/lib/CodeGen/CGCall.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index ec28c1db207a..09ccb63dceeb 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5716,7 +5716,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
,
   assert(unpaddedIndex == 0);
 Builder.CreateStore(elt, eltAddr);
   }
-  // FALLTHROUGH
   [[fallthrough]];
 }
 

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index bd5781a81bb5..194a592fc019 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2121,7 +2121,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
   }
 }
   }
-  // FALLTHROUGH
   [[fallthrough]];
 }
 

diff  --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp 
b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index fed17c77f03d..4fe828bdf768 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -395,7 +395,6 @@ std::optional SValBuilder::getConstantVal(const Expr 
*E) {
   return evalCast(*Val, CE->getType(), SE->getType());
 }
 }
-// FALLTHROUGH
 [[fallthrough]];
   }
 



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


[clang] 0da99ff - [clang][analyzer][NFC] Remove unnecessary casts around Allocate function calls

2023-05-30 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-05-30T18:10:15+02:00
New Revision: 0da99ffe1afc526844f4146c95b4b2ab251de1a9

URL: 
https://github.com/llvm/llvm-project/commit/0da99ffe1afc526844f4146c95b4b2ab251de1a9
DIFF: 
https://github.com/llvm/llvm-project/commit/0da99ffe1afc526844f4146c95b4b2ab251de1a9.diff

LOG: [clang][analyzer][NFC] Remove unnecessary casts around Allocate function 
calls

Reviewed By: steakhal

Differential Revision: https://reviews.llvm.org/D151726

Added: 


Modified: 
clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
clang/lib/StaticAnalyzer/Core/ProgramState.cpp
clang/lib/StaticAnalyzer/Core/SymbolManager.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp 
b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index fc736dd452aa..5a5851975bb6 100644
--- a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -97,7 +97,7 @@ const llvm::APSInt& BasicValueFactory::getValue(const 
llvm::APSInt& X) {
   FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!P) {
-P = (FoldNodeTy*) BPAlloc.Allocate();
+P = BPAlloc.Allocate();
 new (P) FoldNodeTy(X);
 APSIntSet.InsertNode(P, InsertPos);
   }
@@ -132,7 +132,7 @@ BasicValueFactory::getCompoundValData(QualType T,
   CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!D) {
-D = (CompoundValData*) BPAlloc.Allocate();
+D = BPAlloc.Allocate();
 new (D) CompoundValData(T, Vals);
 CompoundValDataSet.InsertNode(D, InsertPos);
   }
@@ -151,7 +151,7 @@ BasicValueFactory::getLazyCompoundValData(const StoreRef 
,
 LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!D) {
-D = (LazyCompoundValData*) BPAlloc.Allocate();
+D = BPAlloc.Allocate();
 new (D) LazyCompoundValData(store, region);
 LazyCompoundValDataSet.InsertNode(D, InsertPos);
   }
@@ -169,7 +169,7 @@ const PointerToMemberData 
*BasicValueFactory::getPointerToMemberData(
   PointerToMemberDataSet.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!D) {
-D = (PointerToMemberData *)BPAlloc.Allocate();
+D = BPAlloc.Allocate();
 new (D) PointerToMemberData(ND, L);
 PointerToMemberDataSet.InsertNode(D, InsertPos);
   }
@@ -358,7 +358,7 @@ BasicValueFactory::getPersistentSValWithData(const SVal& V, 
uintptr_t Data) {
   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!P) {
-P = (FoldNodeTy*) BPAlloc.Allocate();
+P = BPAlloc.Allocate();
 new (P) FoldNodeTy(std::make_pair(V, Data));
 Map.InsertNode(P, InsertPos);
   }
@@ -383,7 +383,7 @@ BasicValueFactory::getPersistentSValPair(const SVal& V1, 
const SVal& V2) {
   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!P) {
-P = (FoldNodeTy*) BPAlloc.Allocate();
+P = BPAlloc.Allocate();
 new (P) FoldNodeTy(std::make_pair(V1, V2));
 Map.InsertNode(P, InsertPos);
   }

diff  --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index cac7ec3f8cf7..314a4feda81b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -408,7 +408,7 @@ ExplodedNode *ExplodedGraph::getNode(const ProgramPoint ,
 }
 else {
   // Allocate a new node.
-  V = (NodeTy*) getAllocator().Allocate();
+  V = getAllocator().Allocate();
 }
 
 ++NumNodes;
@@ -432,7 +432,7 @@ ExplodedNode *ExplodedGraph::createUncachedNode(const 
ProgramPoint ,
 ProgramStateRef State,
 int64_t Id,
 bool IsSink) {
-  NodeTy *V = (NodeTy *) getAllocator().Allocate();
+  NodeTy *V = getAllocator().Allocate();
   new (V) NodeTy(L, State, Id, IsSink);
   return V;
 }

diff  --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp 
b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 90ebbaad2bf3..e90ebab43c78 100644
--- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -424,7 +424,7 @@ ProgramStateRef 
ProgramStateManager::getPersistentState(ProgramState ) {
 freeStates.pop_back();
   }
   else {
-newState = (ProgramState*) Alloc.Allocate();
+newState = Alloc.Allocate();
   }
   new (newState) ProgramState(State);
   StateSet.InsertNode(newState, InsertPos);

diff  --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp 
b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 032605ffe7a2..b4f64bc3a7b3 100644
--- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -170,7 +170,7 @@ SymbolManager::getRegionValueSymbol(const TypedValueRegion* 
R) {
   void *InsertPos;
   SymExpr *SD = 

[clang] ffb4f4d - [ClangTidy] Fix markup in comments

2023-05-17 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-05-17T10:29:10+02:00
New Revision: ffb4f4db73419d9eba81efe00aa0d498f01f6d27

URL: 
https://github.com/llvm/llvm-project/commit/ffb4f4db73419d9eba81efe00aa0d498f01f6d27
DIFF: 
https://github.com/llvm/llvm-project/commit/ffb4f4db73419d9eba81efe00aa0d498f01f6d27.diff

LOG: [ClangTidy] Fix markup in comments

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp

Removed: 




diff  --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
index b46a57f47f982..680c4d11a23b7 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -234,7 +234,7 @@ auto isComparisonOperatorCall(L lhs_arg_matcher, R 
rhs_arg_matcher) {
   hasArgument(1, rhs_arg_matcher));
 }
 
-// Ensures that `Expr` is mapped to a `BoolValue` and returns it.
+/// Ensures that `Expr` is mapped to a `BoolValue` and returns it.
 BoolValue (Environment , const Expr ) {
   auto *Value = cast_or_null(Env.getValue(Expr, SkipPast::None));
   if (Value != nullptr)
@@ -356,7 +356,7 @@ void initializeOptionalReference(const Expr *OptionalExpr,
 }
 
 /// Returns true if and only if `OptionalVal` is initialized and known to be
-/// empty in `Env.
+/// empty in `Env`.
 bool isEmptyOptional(const Value , const Environment ) {
   auto *HasValueVal =
   cast_or_null(OptionalVal.getProperty("has_value"));
@@ -365,7 +365,7 @@ bool isEmptyOptional(const Value , const 
Environment ) {
 }
 
 /// Returns true if and only if `OptionalVal` is initialized and known to be
-/// non-empty in `Env.
+/// non-empty in `Env`.
 bool isNonEmptyOptional(const Value , const Environment ) {
   auto *HasValueVal =
   cast_or_null(OptionalVal.getProperty("has_value"));



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


[clang] ef1b22a - [clang][ClangScanDeps][test] Remove the file before overwriting it

2023-04-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-04-06T13:51:57+02:00
New Revision: ef1b22a20fd4d8c0cfea64089d4e732dd95dc265

URL: 
https://github.com/llvm/llvm-project/commit/ef1b22a20fd4d8c0cfea64089d4e732dd95dc265
DIFF: 
https://github.com/llvm/llvm-project/commit/ef1b22a20fd4d8c0cfea64089d4e732dd95dc265.diff

LOG: [clang][ClangScanDeps][test] Remove the file before overwriting it

Remove the file copied from the source tree before overwriting it. If
the source code is stored with readonly (0444) permissions, then
the copied files are also readonly and attempting to overwrite them
fails.

Added: 


Modified: 
clang/test/ClangScanDeps/modules-pch.c

Removed: 




diff  --git a/clang/test/ClangScanDeps/modules-pch.c 
b/clang/test/ClangScanDeps/modules-pch.c
index aa568e5aaab4d..0f61dd5ecf18c 100644
--- a/clang/test/ClangScanDeps/modules-pch.c
+++ b/clang/test/ClangScanDeps/modules-pch.c
@@ -7,6 +7,7 @@
 
 // Scan dependencies of the PCH:
 //
+// RUN: rm -f %t/cdb_pch.json
 // RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-pch/cdb_pch.json > %t/cdb_pch.json
 // RUN: clang-scan-deps -compilation-database %t/cdb_pch.json -format 
experimental-full \
 // RUN:   -module-files-dir %t/build > %t/result_pch.json
@@ -94,6 +95,7 @@
 
 // Scan dependencies of the TU:
 //
+// RUN: rm -f %t/cdb_tu.json
 // RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-pch/cdb_tu.json > %t/cdb_tu.json
 // RUN: clang-scan-deps -compilation-database %t/cdb_tu.json -format 
experimental-full \
 // RUN:   -module-files-dir %t/build > %t/result_tu.json
@@ -142,6 +144,7 @@
 
 // Scan dependencies of the TU that has common modules with the PCH:
 //
+// RUN: rm -f %t/cdb_tu_with_common.json
 // RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-pch/cdb_tu_with_common.json > 
%t/cdb_tu_with_common.json
 // RUN: clang-scan-deps -compilation-database %t/cdb_tu_with_common.json 
-format experimental-full \
 // RUN:   -module-files-dir %t/build > %t/result_tu_with_common.json



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


[clang] cd11f55 - [clang][dataflow] Fix indentation in a test

2023-03-20 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-03-20T18:34:16+01:00
New Revision: cd11f55a0c6d8524f9ac494d26514d4d72d83435

URL: 
https://github.com/llvm/llvm-project/commit/cd11f55a0c6d8524f9ac494d26514d4d72d83435
DIFF: 
https://github.com/llvm/llvm-project/commit/cd11f55a0c6d8524f9ac494d26514d4d72d83435.diff

LOG: [clang][dataflow] Fix indentation in a test

Added: 


Modified: 
clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp

Removed: 




diff  --git 
a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
index fa7322bc586be..770c7a50195e9 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -134,9 +134,9 @@ TEST_F(EnvironmentTest, 
IncludeFieldsFromDefaultInitializers) {
 
   std::string Code = R"cc(
  struct S {
- S() {}
- int X = 3;
- int Y = X;
+   S() {}
+   int X = 3;
+   int Y = X;
  };
  S foo();
   )cc";



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


[clang] 8bb54da - Allow getRawCommentForDecl to find comments in macros

2023-01-26 Thread Dmitri Gribenko via cfe-commits

Author: Dana Jansens
Date: 2023-01-26T10:12:57+01:00
New Revision: 8bb54da5da3194b71b54f70c6cc55485cf2623b0

URL: 
https://github.com/llvm/llvm-project/commit/8bb54da5da3194b71b54f70c6cc55485cf2623b0
DIFF: 
https://github.com/llvm/llvm-project/commit/8bb54da5da3194b71b54f70c6cc55485cf2623b0.diff

LOG: Allow getRawCommentForDecl to find comments in macros

The key part of getRawCommentForDecl() required to find a comment
is determining where to look for it. The location of the decl
itself is usually right, except when macros get involved. The
comment in the macro is stored in RawCommentList at the spelling
location of the decl, not at the place where the decl comes into
being as the macro is instantiated.

getDeclLocForCommentSearch() already contained to branches to try
handle comments inside macros, and we are able to replace them
and handle more cases as well, by returning the spelling location
of the decl's begin location. That is:
  SourceMgr.getSpellingLoc(D->getBeginLoc())

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D142560

Added: 


Modified: 
clang/lib/AST/ASTContext.cpp
clang/test/Index/annotate-comments-objc.m

Removed: 




diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 3ba8b90898b30..18a041d7a72ab 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -181,22 +181,96 @@ static SourceLocation getDeclLocForCommentSearch(const 
Decl *D,
 
   const SourceLocation DeclLoc = D->getLocation();
   if (DeclLoc.isMacroID()) {
-if (isa(D)) {
-  // If location of the typedef name is in a macro, it is because being
-  // declared via a macro. Try using declaration's starting location as
-  // the "declaration location".
-  return D->getBeginLoc();
-}
-
-if (const auto *TD = dyn_cast(D)) {
-  // If location of the tag decl is inside a macro, but the spelling of
-  // the tag name comes from a macro argument, it looks like a special
-  // macro like NS_ENUM is being used to define the tag decl.  In that
-  // case, adjust the source location to the expansion loc so that we can
-  // attach the comment to the tag decl.
-  if (SourceMgr.isMacroArgExpansion(DeclLoc) && TD->isCompleteDefinition())
-return SourceMgr.getExpansionLoc(DeclLoc);
+// There are (at least) three types of macros we care about here.
+//
+// 1. Macros that are used in the definition of a type outside the macro,
+//with a comment attached at the macro call site.
+//```
+//#define MAKE_NAME(Foo) Name##Foo
+//
+///// Comment is here, where we use the macro.
+//struct MAKE_NAME(Foo) {
+//int a;
+//int b;
+//};
+//```
+// 2. Macros that define whole things along with the comment.
+//```
+//#define MAKE_METHOD(name) \
+//  /** Comment is here, inside the macro. */ \
+//  void name() {}
+//
+//struct S {
+//  MAKE_METHOD(f)
+//}
+//```
+// 3. Macros that both declare a type and name a decl outside the macro.
+//```
+///// Comment is here, where we use the macro.
+//typedef NS_ENUM(NSInteger, Size) {
+//SizeWidth,
+//SizeHeight
+//};
+//```
+//In this case NS_ENUM declares am enum type, and uses the same name 
for
+//the typedef declaration that appears outside the macro. The comment
+//here should be applied to both declarations inside and outside the
+//macro.
+//
+// We have found a Decl name that comes from inside a macro, but
+// Decl::getLocation() returns the place where the macro is being called.
+// If the declaration (and not just the name) resides inside the macro,
+// then we want to map Decl::getLocation() into the macro to where the
+// declaration and its attached comment (if any) were written.
+//
+// This mapping into the macro is done by mapping the location to its
+// spelling location, however even if the declaration is inside a macro,
+// the name's spelling can come from a macro argument (case 2 above). In
+// this case mapping the location to the spelling location finds the
+// argument's position (at `f` in MAKE_METHOD(`f`) above), which is not
+// where the declaration and its comment are located.
+//
+// To avoid this issue, we make use of Decl::getBeginLocation() instead.
+// While the declaration's position is where the name is written, the
+// comment is always attached to the begining of the declaration, not to
+// the name.
+//
+// In the first case, the begin location of the decl is outside the macro,
+// at the location of `typedef`. This is where the comment is found as
+// well. The begin location is not inside a macro, so 

[clang] c8b31da - [clang][dataflow] Allow analyzing multiple functions in unit tests

2023-01-20 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-01-21T01:28:03+01:00
New Revision: c8b31da1ef0a3f2a0ba5c39bb4281b1438e511fb

URL: 
https://github.com/llvm/llvm-project/commit/c8b31da1ef0a3f2a0ba5c39bb4281b1438e511fb
DIFF: 
https://github.com/llvm/llvm-project/commit/c8b31da1ef0a3f2a0ba5c39bb4281b1438e511fb.diff

LOG: [clang][dataflow] Allow analyzing multiple functions in unit tests

In unit tests for concrete dataflow analyses we typically use the
testonly `checkDataflow()` helper to analyse a free function called
"target". This pattern allows our tests to be uniform and focused on
specific statement- or expression-level C++ features.

As we expand our feature coverage, we want to analyze functions whose
names we don't fully control, like constructors, destructors, operators
etc. In such tests it is often convenient to analyze all functions
defined in the input code, to avoid having to carefully craft an AST
matcher that finds the exact function we're interested in. That can be
easily done by providing `checkDataflow()` with a catch-all matcher like
`functionDecl()`.

It is also often convenient to define multiple special member functions
in a single unit test, for example, multiple constructors, and share the
rest of the class definition code between constructors. As a result, it
makes sense to analyze multiple functions in one unit test.

This change allows `checkDataflow()` to correctly handle AST matchers
that match more than one function. Previously, it would only ever
analyze the first matched function, and silently ignore the rest. Now it
runs dataflow analysis in a loop, and calls `VerifyResults` for each
function that was found in the input and analyzed.

Reviewed By: ymandel, sgatev

Differential Revision: https://reviews.llvm.org/D140859

Added: 


Modified: 
clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
clang/unittests/Analysis/FlowSensitive/TestingSupport.h
clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp

Removed: 




diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp 
b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
index 8541ac336b6e..0d441b71e69c 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
@@ -6,6 +6,7 @@
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Lexer.h"
@@ -45,18 +46,23 @@ isAnnotationDirectlyAfterStatement(const Stmt *Stmt, 
unsigned AnnotationBegin,
   return true;
 }
 
-llvm::DenseMap
-test::buildLineToAnnotationMapping(SourceManager ,
-   llvm::Annotations AnnotatedCode) {
+llvm::DenseMap test::buildLineToAnnotationMapping(
+const SourceManager , const LangOptions ,
+SourceRange BoundingRange, llvm::Annotations AnnotatedCode) {
+  CharSourceRange CharBoundingRange =
+  Lexer::getAsCharRange(BoundingRange, SM, LangOpts);
+
   llvm::DenseMap LineNumberToContent;
   auto Code = AnnotatedCode.code();
   auto Annotations = AnnotatedCode.ranges();
   for (auto  : Annotations) {
-auto LineNumber =
-SM.getPresumedLineNumber(SM.getLocForStartOfFile(SM.getMainFileID())
- .getLocWithOffset(AnnotationRange.Begin));
-auto Content = Code.slice(AnnotationRange.Begin, 
AnnotationRange.End).str();
-LineNumberToContent[LineNumber] = Content;
+SourceLocation Loc = SM.getLocForStartOfFile(SM.getMainFileID())
+ .getLocWithOffset(AnnotationRange.Begin);
+if (SM.isPointWithin(Loc, CharBoundingRange.getBegin(),
+ CharBoundingRange.getEnd())) {
+  LineNumberToContent[SM.getPresumedLineNumber(Loc)] =
+  Code.slice(AnnotationRange.Begin, AnnotationRange.End).str();
+}
   }
   return LineNumberToContent;
 }
@@ -83,11 +89,18 @@ test::buildStatementToAnnotationMapping(const FunctionDecl 
*Func,
 Stmts[Offset] = S;
   }
 
-  unsigned I = 0;
-  auto Annotations = AnnotatedCode.ranges();
+  unsigned FunctionBeginOffset =
+  SourceManager.getFileOffset(Func->getBeginLoc());
+  unsigned FunctionEndOffset = SourceManager.getFileOffset(Func->getEndLoc());
+
+  std::vector Annotations = AnnotatedCode.ranges();
+  llvm::erase_if(Annotations, [=](llvm::Annotations::Range R) {
+return R.Begin < FunctionBeginOffset || R.End >= FunctionEndOffset;
+  });
   std::reverse(Annotations.begin(), Annotations.end());
   auto Code = AnnotatedCode.code();
 
+  unsigned I = 0;
   for (auto OffsetAndStmt = Stmts.rbegin(); OffsetAndStmt != Stmts.rend();
OffsetAndStmt++) {
 unsigned Offset = OffsetAndStmt->first;

diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h 

[clang] 0a11a1b - [OpenMP] Fix a test that fails when 'libgomp' is the default library

2023-01-12 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-01-12T09:54:42+01:00
New Revision: 0a11a1b1868dd2ab183c4313ccbfbe126e91ca08

URL: 
https://github.com/llvm/llvm-project/commit/0a11a1b1868dd2ab183c4313ccbfbe126e91ca08
DIFF: 
https://github.com/llvm/llvm-project/commit/0a11a1b1868dd2ab183c4313ccbfbe126e91ca08.diff

LOG: [OpenMP] Fix a test that fails when 'libgomp' is the default library

We can't do offloading with libgomp, thus the test fails. This change
explicitly chooses an OpenMP runtime library that is capable of
offloading.

This change is similar to
https://github.com/llvm/llvm-project/commit/a5098e5f27badc3ba16533418accd2e17641e4e4.

Added: 


Modified: 
clang/test/Driver/openmp-system-arch.c

Removed: 




diff  --git a/clang/test/Driver/openmp-system-arch.c 
b/clang/test/Driver/openmp-system-arch.c
index c9219234ede5..b99522269902 100644
--- a/clang/test/Driver/openmp-system-arch.c
+++ b/clang/test/Driver/openmp-system-arch.c
@@ -19,41 +19,41 @@
 // RUN: chmod +x %t/nvptx_arch_empty
 
 // case when nvptx-arch and amdgpu-arch return nothing or fails
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch=native \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch=native \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_fail 
--amdgpu-arch-tool=%t/amdgpu_arch_fail %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch=native \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch=native \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_empty 
--amdgpu-arch-tool=%t/amdgpu_arch_empty %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch= \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch= \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_fail 
--amdgpu-arch-tool=%t/amdgpu_arch_fail %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch= \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch= \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_empty 
--amdgpu-arch-tool=%t/amdgpu_arch_empty %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
 // NO-OUTPUT-ERROR: error: failed to deduce triple for target architecture 
'native'; specify the triple using '-fopenmp-targets' and '-Xopenmp-target' 
instead.
 
 // case when amdgpu-arch succeeds.
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch=native \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch=native \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_fail 
--amdgpu-arch-tool=%t/amdgpu_arch_gfx906 %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=ARCH-GFX906
 // ARCH-GFX906: "-cc1" "-triple" "amdgcn-amd-amdhsa"{{.*}}"-target-cpu" 
"gfx906"
 
 // case when nvptx-arch succeeds.
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch=native \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch=native \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_sm_70 
--amdgpu-arch-tool=%t/amdgpu_arch_fail %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=ARCH-SM_70
 // ARCH-SM_70: "-cc1" "-triple" "nvptx64-nvidia-cuda"{{.*}}"-target-cpu" 
"sm_70"
 
 // case when both nvptx-arch and amdgpu-arch succeed.
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch=native \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch=native \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_sm_70 
--amdgpu-arch-tool=%t/amdgpu_arch_gfx906 %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=ARCH-SM_70-GFX906
 // ARCH-SM_70-GFX906: "-cc1" "-triple" "amdgcn-amd-amdhsa"{{.*}}"-target-cpu" 
"gfx906"
 // ARCH-SM_70-GFX906: "-cc1" "-triple" 
"nvptx64-nvidia-cuda"{{.*}}"-target-cpu" "sm_70"
 
 // case when both nvptx-arch and amdgpu-arch succeed with other archs.
-// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp 
--offload-arch=native,sm_75,gfx1030 \
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu -nogpulib 
-fopenmp=libomp --offload-arch=native,sm_75,gfx1030 \
 // RUN: --nvptx-arch-tool=%t/nvptx_arch_sm_70 
--amdgpu-arch-tool=%t/amdgpu_arch_gfx906 %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=ARCH-MULTIPLE
 // ARCH-MULTIPLE: "-cc1" "-triple" "amdgcn-amd-amdhsa"{{.*}}"-target-cpu" 
"gfx1030"



___
cfe-commits mailing list

[clang] 5674385 - [clang][dataflow] Remove unused includes

2023-01-02 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2023-01-02T23:34:24+01:00
New Revision: 5674385577f144db2131278449665994acff035c

URL: 
https://github.com/llvm/llvm-project/commit/5674385577f144db2131278449665994acff035c
DIFF: 
https://github.com/llvm/llvm-project/commit/5674385577f144db2131278449665994acff035c.diff

LOG: [clang][dataflow] Remove unused includes

Added: 


Modified: 
clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp

Removed: 




diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp 
b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
index 42ee23c4be4f5..f73933f3db3d4 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
@@ -4,18 +4,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
-#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Lexer.h"
-#include "clang/Serialization/PCHContainerOperations.h"
-#include "clang/Tooling/ArgumentsAdjusters.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"



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


[clang] d273863 - [clang] Remove deprecated ControlFlowContext::build()

2022-12-23 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-12-23T15:06:59+01:00
New Revision: d27386384a2a414bcd7c7a18491db32f4ca86881

URL: 
https://github.com/llvm/llvm-project/commit/d27386384a2a414bcd7c7a18491db32f4ca86881
DIFF: 
https://github.com/llvm/llvm-project/commit/d27386384a2a414bcd7c7a18491db32f4ca86881.diff

LOG: [clang] Remove deprecated ControlFlowContext::build()

Reviewed By: merrymeerkat

Differential Revision: https://reviews.llvm.org/D140625

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h 
b/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
index 58e901fac0047..e641468f77d00 100644
--- a/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
@@ -35,10 +35,6 @@ class ControlFlowContext {
   static llvm::Expected build(const Decl *D, Stmt ,
   ASTContext );
 
-  // DEPRECATED. Use overload above.
-  static llvm::Expected build(const Decl *D, Stmt *S,
-  ASTContext *C);
-
   /// Returns the `Decl` containing the statement used to construct the CFG, if
   /// available.
   const Decl *getDecl() const { return ContainingDecl; }

diff  --git a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp 
b/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
index 2bdb1cdcc9534..2492b5203724c 100644
--- a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -67,12 +67,5 @@ ControlFlowContext::build(const Decl *D, Stmt , ASTContext 
) {
   return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock));
 }
 
-llvm::Expected
-ControlFlowContext::build(const Decl *D, Stmt *S, ASTContext *C) {
-  assert(S != nullptr);
-  assert(C != nullptr);
-  return build(D, *S, *C);
-}
-
 } // namespace dataflow
 } // namespace clang



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


[clang-tools-extra] 3a39b0a - [clang] Migrate away from a deprecated Clang CFG factory function

2022-12-23 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-12-23T14:36:52+01:00
New Revision: 3a39b0ac1a72a2fb554e2ccc286003da5166faeb

URL: 
https://github.com/llvm/llvm-project/commit/3a39b0ac1a72a2fb554e2ccc286003da5166faeb
DIFF: 
https://github.com/llvm/llvm-project/commit/3a39b0ac1a72a2fb554e2ccc286003da5166faeb.diff

LOG: [clang] Migrate away from a deprecated Clang CFG factory function

Reviewed By: merrymeerkat

Differential Revision: https://reviews.llvm.org/D140620

Added: 


Modified: 
clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
index c97917ebc3e05..ccf9365940191 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
@@ -43,7 +43,7 @@ analyzeFunction(const FunctionDecl , ASTContext 
,
   using llvm::Expected;
 
   Expected Context =
-  ControlFlowContext::build(, FuncDecl.getBody(), );
+  ControlFlowContext::build(, *FuncDecl.getBody(), ASTCtx);
   if (!Context)
 return std::nullopt;
 

diff  --git 
a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
index 8e0e27efae9e8..31d51173d29b2 100644
--- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -68,7 +68,7 @@ runAnalysis(llvm::StringRef Code, AnalysisT 
(*MakeAnalysis)(ASTContext &)) {
   assert(Body != nullptr);
 
   auto CFCtx = llvm::cantFail(
-  ControlFlowContext::build(nullptr, Body, >getASTContext()));
+  ControlFlowContext::build(nullptr, *Body, AST->getASTContext()));
 
   AnalysisT Analysis = MakeAnalysis(AST->getASTContext());
   DataflowAnalysisContext DACtx(std::make_unique());



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


[clang] 0da4cec - [clang][dataflow] Remove unused argument in getNullability

2022-12-16 Thread Dmitri Gribenko via cfe-commits

Author: Dani Ferreira Franco Moura
Date: 2022-12-16T12:22:23+01:00
New Revision: 0da4cecfb6ad14ee0f0f9fa904e685fd6b64be60

URL: 
https://github.com/llvm/llvm-project/commit/0da4cecfb6ad14ee0f0f9fa904e685fd6b64be60
DIFF: 
https://github.com/llvm/llvm-project/commit/0da4cecfb6ad14ee0f0f9fa904e685fd6b64be60.diff

LOG: [clang][dataflow] Remove unused argument in getNullability

This change will allow users to call getNullability() without providing an 
ASTContext.

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D140104

Added: 


Modified: 
clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/Type.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Type.cpp
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclObjC.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprObjC.cpp
clang/lib/Sema/SemaLambda.cpp
clang/lib/Sema/SemaObjCProperty.cpp
clang/lib/Sema/SemaType.cpp
clang/tools/libclang/CXType.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp 
b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
index 2b527142f0d26..f3cfee0570fb6 100644
--- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -874,7 +874,7 @@ void foo(int *x);
   auto AST = TU.build();
   EXPECT_THAT(*AST.getDiagnostics(), IsEmpty());
   const auto *X = cast(findDecl(AST, "foo")).getParamDecl(0);
-  ASSERT_TRUE(X->getOriginalType()->getNullability(X->getASTContext()) ==
+  ASSERT_TRUE(X->getOriginalType()->getNullability() ==
   NullabilityKind::NonNull);
 }
 
@@ -892,10 +892,10 @@ void bar(int *Y);
   EXPECT_THAT(*AST.getDiagnostics(),
   ElementsAre(diagName("pp_eof_in_assume_nonnull")));
   const auto *X = cast(findDecl(AST, "foo")).getParamDecl(0);
-  ASSERT_TRUE(X->getOriginalType()->getNullability(X->getASTContext()) ==
+  ASSERT_TRUE(X->getOriginalType()->getNullability() ==
   NullabilityKind::NonNull);
   const auto *Y = cast(findDecl(AST, "bar")).getParamDecl(0);
-  ASSERT_FALSE(Y->getOriginalType()->getNullability(X->getASTContext()));
+  ASSERT_FALSE(Y->getOriginalType()->getNullability());
 }
 
 TEST(DiagnosticsTest, InsideMacros) {

diff  --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 63f48d9ae9871..64cdd63db009f 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2548,8 +2548,8 @@ class ASTContext : public RefCountedBase {
 
   bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,
bool IsParam) const {
-auto SubTnullability = SubT->getNullability(*this);
-auto SuperTnullability = SuperT->getNullability(*this);
+auto SubTnullability = SubT->getNullability();
+auto SuperTnullability = SuperT->getNullability();
 if (SubTnullability.has_value() == SuperTnullability.has_value()) {
   // Neither has nullability; return true
   if (!SubTnullability)

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 87cb433177dfa..70f2132e0456f 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2547,7 +2547,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
   /// Note that nullability is only captured as sugar within the type
   /// system, not as part of the canonical type, so nullability will
   /// be lost by canonicalization and desugaring.
-  Optional getNullability(const ASTContext ) const;
+  Optional getNullability() const;
+  // TODO: Remove overload.
+  Optional getNullability(const ASTContext &) const;
 
   /// Determine whether the given type can have a nullability
   /// specifier applied to it, i.e., if it is any kind of pointer type.

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 9aaf7cc6565cb..8887789555afb 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6975,7 +6975,7 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) 
const {
  
PrettyArrayType->getIndexTypeQualifiers());
 
   // int x[_Nullable] -> int * _Nullable
-  if (auto Nullability = Ty->getNullability(*this)) {
+  if (auto Nullability = Ty->getNullability()) {
 Result = const_cast(this)->getAttributedType(
 AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
   }

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 62383c671f92c..fe7bbcd1479dd 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -4141,8 +4141,7 @@ LinkageInfo 

[clang] 4ca1ae5 - [clang][dataflow] Remove old diagnoser API

2022-12-14 Thread Dmitri Gribenko via cfe-commits

Author: Dani Ferreira Franco Moura
Date: 2022-12-14T20:45:48+01:00
New Revision: 4ca1ae580b0ce44c3a83992cf3abae45c3a229b4

URL: 
https://github.com/llvm/llvm-project/commit/4ca1ae580b0ce44c3a83992cf3abae45c3a229b4
DIFF: 
https://github.com/llvm/llvm-project/commit/4ca1ae580b0ce44c3a83992cf3abae45c3a229b4.diff

LOG: [clang][dataflow] Remove old diagnoser API

This is a clean up following the revision D139868 
(https://reviews.llvm.org/D139868).

Reviewed By: gribozavr2, ymandel

Differential Revision: https://reviews.llvm.org/D140037

Added: 


Modified: 
clang/unittests/Analysis/FlowSensitive/TestingSupport.h

Removed: 




diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h 
b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index d20e1ed0d34fd..c72e8e47dd8e3 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -125,20 +125,6 @@ template  struct AnalysisInputs {
 PostVisitCFG = std::move(Arg);
 return std::move(*this);
   }
-
-  AnalysisInputs &&
-  withPostVisitCFG(std::function
-   Arg) && {
-PostVisitCFG =
-[Arg = std::move(Arg)](ASTContext , const CFGElement ,
-const TransferStateForDiagnostics
-) {
-  Arg(Context, Element,
-  TypeErasedDataflowAnalysisState({State.Lattice}, State.Env));
-};
-return std::move(*this);
-  }
   AnalysisInputs &(ArrayRef Arg) && {
 ASTBuildArgs = std::move(Arg);
 return std::move(*this);



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


[clang] 82d50fe - [clang][dataflow] Change the diagnoser API to receive a correctly typed lattice element

2022-12-13 Thread Dmitri Gribenko via cfe-commits

Author: Dani Ferreira Franco Moura
Date: 2022-12-13T14:49:07+01:00
New Revision: 82d50fef9b7c1dfdff7f9265340fde40a34870cf

URL: 
https://github.com/llvm/llvm-project/commit/82d50fef9b7c1dfdff7f9265340fde40a34870cf
DIFF: 
https://github.com/llvm/llvm-project/commit/82d50fef9b7c1dfdff7f9265340fde40a34870cf.diff

LOG: [clang][dataflow] Change the diagnoser API to receive a correctly typed 
lattice element

Previously, the diagnoser could only receive the Environment at a given program 
point. Now, it receives the complete dataflow state: the environment and 
lattice element.

This change does not contain any tests because we modify the checkDataflow 
function to rely on the newly introduced lattice element in PostVisitCFG, and 
existing tests that verify lattice elements depend on this overload of 
checkDataflow.

Reviewed By: gribozavr2, ymandel

Differential Revision: https://reviews.llvm.org/D139868

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
clang/unittests/Analysis/FlowSensitive/TestingSupport.h
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h 
b/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
index 76d18c1d24463..37894ab37dd8d 100644
--- a/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
+++ b/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
@@ -48,6 +48,16 @@ template  struct TransferState {
   Environment 
 };
 
+/// A read-only version of TransferState.
+template  struct TransferStateForDiagnostics {
+  TransferStateForDiagnostics(const LatticeT , const Environment )
+  : Lattice(Lattice), Env(Env) {}
+
+  /// Current lattice element.
+  const LatticeT 
+  const Environment 
+};
+
 template 
 using MatchSwitchMatcher = ast_matchers::internal::Matcher;
 

diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h 
b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 511ff71ed1d43..d20e1ed0d34fd 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -30,6 +30,7 @@
 #include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Serialization/PCHContainerOperations.h"
@@ -116,11 +117,26 @@ template  struct AnalysisInputs {
 SetupTest = std::move(Arg);
 return std::move(*this);
   }
+  AnalysisInputs &(
+  std::function &)>
+  Arg) && {
+PostVisitCFG = std::move(Arg);
+return std::move(*this);
+  }
+
   AnalysisInputs &&
   withPostVisitCFG(std::function
Arg) && {
-PostVisitCFG = std::move(Arg);
+PostVisitCFG =
+[Arg = std::move(Arg)](ASTContext , const CFGElement ,
+const TransferStateForDiagnostics
+) {
+  Arg(Context, Element,
+  TypeErasedDataflowAnalysisState({State.Lattice}, State.Env));
+};
 return std::move(*this);
   }
   AnalysisInputs &(ArrayRef Arg) && {
@@ -148,8 +164,9 @@ template  struct AnalysisInputs {
   std::function SetupTest = nullptr;
   /// Optional. If provided, this function is applied on each CFG element after
   /// the analysis has been run.
-  std::function
+  std::function &)>
   PostVisitCFG = nullptr;
 
   /// Optional. Options for building the AST context.
@@ -226,11 +243,15 @@ checkDataflow(AnalysisInputs AI,
  const TypeErasedDataflowAnalysisState &)>
   PostVisitCFGClosure = nullptr;
   if (AI.PostVisitCFG) {
-PostVisitCFGClosure =
-[, ](const CFGElement ,
-const TypeErasedDataflowAnalysisState ) {
-  AI.PostVisitCFG(Context, Element, State);
-};
+PostVisitCFGClosure = [, ](
+  const CFGElement ,
+  const TypeErasedDataflowAnalysisState ) {
+  AI.PostVisitCFG(Context, Element,
+  TransferStateForDiagnostics(
+  llvm::any_cast(
+  State.Lattice.Value),
+  State.Env));
+};
   }
 
   // Additional test setup.
@@ -326,28 +347,28 @@ checkDataflow(AnalysisInputs AI,
   // Save the states computed for program points immediately following 
annotated
   // statements. The saved states are keyed by the content of the annotation.
   llvm::StringMap AnnotationStates;
-  auto PostVisitCFG = [, ,
-   PrevPostVisitCFG = std::move(AI.PostVisitCFG)](
-  ASTContext , const CFGElement ,
-  const 

[clang] 4d1c5b9 - [openmp] Fix a doc comment issue found by -Wdocumentation

2022-12-11 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-12-12T00:14:01+01:00
New Revision: 4d1c5b946ad7f10d398b43e7f20a528407fb79b9

URL: 
https://github.com/llvm/llvm-project/commit/4d1c5b946ad7f10d398b43e7f20a528407fb79b9
DIFF: 
https://github.com/llvm/llvm-project/commit/4d1c5b946ad7f10d398b43e7f20a528407fb79b9.diff

LOG: [openmp] Fix a doc comment issue found by -Wdocumentation

Added: 


Modified: 
clang/include/clang/Sema/MultiplexExternalSemaSource.h

Removed: 




diff  --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h 
b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
index 704925577d269..b0bb15eccee1d 100644
--- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -55,7 +55,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource 
{
 
   /// Appends new source to the source list.
   ///
-  ///\param[in] source - An ExternalSemaSource.
+  ///\param[in] Source - An ExternalSemaSource.
   ///
   void AddSource(ExternalSemaSource *Source);
 



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


[clang] 8d43423 - [openmp] Fix a doc comment issue found by -Wdocumentation

2022-12-11 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-12-11T23:58:28+01:00
New Revision: 8d434235569fe4472c5de43d5f97e3a0bd1f

URL: 
https://github.com/llvm/llvm-project/commit/8d434235569fe4472c5de43d5f97e3a0bd1f
DIFF: 
https://github.com/llvm/llvm-project/commit/8d434235569fe4472c5de43d5f97e3a0bd1f.diff

LOG: [openmp] Fix a doc comment issue found by -Wdocumentation

Added: 


Modified: 
clang/include/clang/AST/OpenMPClause.h

Removed: 




diff  --git a/clang/include/clang/AST/OpenMPClause.h 
b/clang/include/clang/AST/OpenMPClause.h
index 59b763335fe2d..3070f573b41d1 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -1747,7 +1747,7 @@ class OMPMessageClause final : public OMPClause {
 public:
   /// Build 'message' clause with message string argument
   ///
-  /// \param A Argument of the clause (message string).
+  /// \param MS Argument of the clause (message string).
   /// \param StartLoc Starting location of the clause.
   /// \param LParenLoc Location of '('.
   /// \param EndLoc Ending location of the clause.



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


[clang] 3c50f0d - Add const information about AST nodes used to construct CFG elements.

2022-11-08 Thread Dmitri Gribenko via cfe-commits

Author: Dani Ferreira Franco Moura
Date: 2022-11-08T12:11:38+01:00
New Revision: 3c50f0d879bf73e7cf64c83017ccb442d780aae6

URL: 
https://github.com/llvm/llvm-project/commit/3c50f0d879bf73e7cf64c83017ccb442d780aae6
DIFF: 
https://github.com/llvm/llvm-project/commit/3c50f0d879bf73e7cf64c83017ccb442d780aae6.diff

LOG: Add const information about AST nodes used to construct CFG elements.

Most constructors and destructors in CFG.h already specify const arguments, but 
some are missing this.

Reviewed By: gribozavr2, krasimir

Differential Revision: https://reviews.llvm.org/D137584

Added: 


Modified: 
clang/include/clang/Analysis/CFG.h

Removed: 




diff  --git a/clang/include/clang/Analysis/CFG.h 
b/clang/include/clang/Analysis/CFG.h
index 9212276a3f691..96231fe0c2c6d 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -131,7 +131,7 @@ class CFGElement {
 
 class CFGStmt : public CFGElement {
 public:
-  explicit CFGStmt(Stmt *S, Kind K = Statement) : CFGElement(K, S) {
+  explicit CFGStmt(const Stmt *S, Kind K = Statement) : CFGElement(K, S) {
 assert(isKind(*this));
   }
 
@@ -155,7 +155,8 @@ class CFGStmt : public CFGElement {
 /// this is only used by the analyzer's CFG.
 class CFGConstructor : public CFGStmt {
 public:
-  explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
+  explicit CFGConstructor(const CXXConstructExpr *CE,
+  const ConstructionContext *C)
   : CFGStmt(CE, Constructor) {
 assert(C);
 Data2.setPointer(const_cast(C));
@@ -185,7 +186,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
 public:
   /// Returns true when call expression \p CE needs to be represented
   /// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
-  static bool isCXXRecordTypedCall(Expr *E) {
+  static bool isCXXRecordTypedCall(const Expr *E) {
 assert(isa(E) || isa(E));
 // There is no such thing as reference-type expression. If the function
 // returns a reference, it'll return the respective lvalue or xvalue
@@ -194,7 +195,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
E->getType().getCanonicalType()->getAsCXXRecordDecl();
   }
 
-  explicit CFGCXXRecordTypedCall(Expr *E, const ConstructionContext *C)
+  explicit CFGCXXRecordTypedCall(const Expr *E, const ConstructionContext *C)
   : CFGStmt(E, CXXRecordTypedCall) {
 assert(isCXXRecordTypedCall(E));
 assert(C && (isa(C) ||
@@ -225,7 +226,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
 /// list.
 class CFGInitializer : public CFGElement {
 public:
-  explicit CFGInitializer(CXXCtorInitializer *initializer)
+  explicit CFGInitializer(const CXXCtorInitializer *initializer)
   : CFGElement(Initializer, initializer) {}
 
   CXXCtorInitializer* getInitializer() const {
@@ -482,7 +483,7 @@ class CFGMemberDtor : public CFGImplicitDtor {
 /// expression for temporary object.
 class CFGTemporaryDtor : public CFGImplicitDtor {
 public:
-  CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
+  CFGTemporaryDtor(const CXXBindTemporaryExpr *expr)
   : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
 
   const CXXBindTemporaryExpr *getBindTemporaryExpr() const {



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


[clang] 941959d - [clang][dataflow] Use llvm::is_contained()

2022-08-16 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-08-16T19:59:21+02:00
New Revision: 941959d69de76342fbeebcebd9f0ebdf2f73c77d

URL: 
https://github.com/llvm/llvm-project/commit/941959d69de76342fbeebcebd9f0ebdf2f73c77d
DIFF: 
https://github.com/llvm/llvm-project/commit/941959d69de76342fbeebcebd9f0ebdf2f73c77d.diff

LOG: [clang][dataflow] Use llvm::is_contained()

Reviewed By: samestep, xazax.hun

Differential Revision: https://reviews.llvm.org/D131975

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Removed: 




diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index f64ade34bcb82..9acd993eb25da 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -20,6 +20,7 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include 
@@ -207,9 +208,7 @@ Environment::Environment(DataflowAnalysisContext ,
 
 bool Environment::canDescend(unsigned MaxDepth,
  const DeclContext *Callee) const {
-  return CallStack.size() <= MaxDepth &&
- std::find(CallStack.begin(), CallStack.end(), Callee) ==
- CallStack.end();
+  return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, 
Callee);
 }
 
 Environment Environment::pushCall(const CallExpr *Call) const {



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


[clang] b5e3dac - [clang][dataflow] Add explicit "AST" nodes for implications and iff

2022-07-26 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-26T14:19:22+02:00
New Revision: b5e3dac33d42cdf8a3b19b1f64b726e700363ded

URL: 
https://github.com/llvm/llvm-project/commit/b5e3dac33d42cdf8a3b19b1f64b726e700363ded
DIFF: 
https://github.com/llvm/llvm-project/commit/b5e3dac33d42cdf8a3b19b1f64b726e700363ded.diff

LOG: [clang][dataflow] Add explicit "AST" nodes for implications and iff

Previously we used to desugar implications and biconditionals into
equivalent CNF/DNF as soon as possible. However, this desugaring makes
debug output (Environment::dump()) less readable than it could be.
Therefore, it makes sense to keep the sugared representation of a
boolean formula, and desugar it in the solver.

Reviewed By: sgatev, xazax.hun, wyt

Differential Revision: https://reviews.llvm.org/D130519

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/Value.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp
clang/unittests/Analysis/FlowSensitive/SolverTest.cpp
clang/unittests/Analysis/FlowSensitive/TestingSupport.h

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index abc3183e1b0b5..b3e725ad3f6a5 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -340,6 +340,10 @@ class DataflowAnalysisContext {
   llvm::DenseMap, DisjunctionValue *>
   DisjunctionVals;
   llvm::DenseMap NegationVals;
+  llvm::DenseMap, ImplicationValue *>
+  ImplicationVals;
+  llvm::DenseMap, BiconditionalValue *>
+  BiconditionalVals;
 
   // Flow conditions are tracked symbolically: each unique flow condition is
   // associated with a fresh symbolic variable (token), bound to the clause 
that

diff  --git a/clang/include/clang/Analysis/FlowSensitive/Value.h 
b/clang/include/clang/Analysis/FlowSensitive/Value.h
index 70348f8745431..c63799fe6a464 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Value.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Value.h
@@ -37,12 +37,13 @@ class Value {
 Pointer,
 Struct,
 
-// Synthetic boolean values are either atomic values or composites that
-// represent conjunctions, disjunctions, and negations.
+// Synthetic boolean values are either atomic values or logical 
connectives.
 AtomicBool,
 Conjunction,
 Disjunction,
-Negation
+Negation,
+Implication,
+Biconditional,
   };
 
   explicit Value(Kind ValKind) : ValKind(ValKind) {}
@@ -84,7 +85,9 @@ class BoolValue : public Value {
 return Val->getKind() == Kind::AtomicBool ||
Val->getKind() == Kind::Conjunction ||
Val->getKind() == Kind::Disjunction ||
-   Val->getKind() == Kind::Negation;
+   Val->getKind() == Kind::Negation ||
+   Val->getKind() == Kind::Implication ||
+   Val->getKind() == Kind::Biconditional;
   }
 };
 
@@ -162,6 +165,54 @@ class NegationValue : public BoolValue {
   BoolValue 
 };
 
+/// Models a boolean implication.
+///
+/// Equivalent to `!LHS v RHS`.
+class ImplicationValue : public BoolValue {
+public:
+  explicit ImplicationValue(BoolValue , BoolValue )
+  : BoolValue(Kind::Implication), LeftSubVal(LeftSubVal),
+RightSubVal(RightSubVal) {}
+
+  static bool classof(const Value *Val) {
+return Val->getKind() == Kind::Implication;
+  }
+
+  /// Returns the left sub-value of the implication.
+  BoolValue () const { return LeftSubVal; }
+
+  /// Returns the right sub-value of the implication.
+  BoolValue () const { return RightSubVal; }
+
+private:
+  BoolValue 
+  BoolValue 
+};
+
+/// Models a boolean biconditional.
+///
+/// Equivalent to `(LHS ^ RHS) v (!LHS ^ !RHS)`.
+class BiconditionalValue : public BoolValue {
+public:
+  explicit BiconditionalValue(BoolValue , BoolValue )
+  : BoolValue(Kind::Biconditional), LeftSubVal(LeftSubVal),
+RightSubVal(RightSubVal) {}
+
+  static bool classof(const Value *Val) {
+return Val->getKind() == Kind::Biconditional;
+  }
+
+  /// Returns the left sub-value of the biconditional.
+  BoolValue () const { return LeftSubVal; }
+
+  /// Returns the right sub-value of the biconditional.
+  BoolValue () const { return RightSubVal; }
+
+private:
+  BoolValue 
+  BoolValue 
+};
+
 /// Models an integer.
 class IntegerValue : public Value {
 public:

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 

[clang] 3281138 - [clang][dataflow] Fix SAT solver crashes on `X ^ X` and `X v X`

2022-07-26 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-26T10:26:44+02:00
New Revision: 3281138aad80fcefc7f266c7e3b2e359d5dbc8da

URL: 
https://github.com/llvm/llvm-project/commit/3281138aad80fcefc7f266c7e3b2e359d5dbc8da
DIFF: 
https://github.com/llvm/llvm-project/commit/3281138aad80fcefc7f266c7e3b2e359d5dbc8da.diff

LOG: [clang][dataflow] Fix SAT solver crashes on `X ^ X` and `X v X`

BooleanFormula::addClause has an invariant that a clause has no duplicated
literals. When the solver was desugaring a formula into CNF clauses, it
could construct a clause with such duplicated literals in two cases.

Reviewed By: sgatev, ymandel, xazax.hun

Differential Revision: https://reviews.llvm.org/D130522

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
clang/unittests/Analysis/FlowSensitive/SolverTest.cpp

Removed: 




diff  --git a/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp 
b/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
index 6a3948bd1fea0..b081543ac1333 100644
--- a/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
+++ b/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
@@ -263,30 +263,52 @@ BooleanFormula buildBooleanFormula(const 
llvm::DenseSet ) {
   const Variable LeftSubVar = GetVar(>getLeftSubValue());
   const Variable RightSubVar = GetVar(>getRightSubValue());
 
-  // `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v !B)`
-  // which is already in conjunctive normal form. Below we add each of the
-  // conjuncts of the latter expression to the result.
-  Formula.addClause(negLit(Var), posLit(LeftSubVar));
-  Formula.addClause(negLit(Var), posLit(RightSubVar));
-  Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar));
-
-  // Visit the sub-values of `Val`.
-  UnprocessedSubVals.push(>getLeftSubValue());
-  UnprocessedSubVals.push(>getRightSubValue());
+  if (LeftSubVar == RightSubVar) {
+// `X <=> (A ^ A)` is equivalent to `(!X v A) ^ (X v !A)` which is
+// already in conjunctive normal form. Below we add each of the
+// conjuncts of the latter expression to the result.
+Formula.addClause(negLit(Var), posLit(LeftSubVar));
+Formula.addClause(posLit(Var), negLit(LeftSubVar));
+
+// Visit a sub-value of `Val` (pick any, they are identical).
+UnprocessedSubVals.push(>getLeftSubValue());
+  } else {
+// `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v 
!B)`
+// which is already in conjunctive normal form. Below we add each of 
the
+// conjuncts of the latter expression to the result.
+Formula.addClause(negLit(Var), posLit(LeftSubVar));
+Formula.addClause(negLit(Var), posLit(RightSubVar));
+Formula.addClause(posLit(Var), negLit(LeftSubVar), 
negLit(RightSubVar));
+
+// Visit the sub-values of `Val`.
+UnprocessedSubVals.push(>getLeftSubValue());
+UnprocessedSubVals.push(>getRightSubValue());
+  }
 } else if (auto *D = dyn_cast(Val)) {
   const Variable LeftSubVar = GetVar(>getLeftSubValue());
   const Variable RightSubVar = GetVar(>getRightSubValue());
 
-  // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v !B)`
-  // which is already in conjunctive normal form. Below we add each of the
-  // conjuncts of the latter expression to the result.
-  Formula.addClause(negLit(Var), posLit(LeftSubVar), posLit(RightSubVar));
-  Formula.addClause(posLit(Var), negLit(LeftSubVar));
-  Formula.addClause(posLit(Var), negLit(RightSubVar));
+  if (LeftSubVar == RightSubVar) {
+// `X <=> (A v A)` is equivalent to `(!X v A) ^ (X v !A)` which is
+// already in conjunctive normal form. Below we add each of the
+// conjuncts of the latter expression to the result.
+Formula.addClause(negLit(Var), posLit(LeftSubVar));
+Formula.addClause(posLit(Var), negLit(LeftSubVar));
 
-  // Visit the sub-values of `Val`.
-  UnprocessedSubVals.push(>getLeftSubValue());
-  UnprocessedSubVals.push(>getRightSubValue());
+// Visit a sub-value of `Val` (pick any, they are identical).
+UnprocessedSubVals.push(>getLeftSubValue());
+  } else {
+// `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v 
!B)`
+// which is already in conjunctive normal form. Below we add each of 
the
+// conjuncts of the latter expression to the result.
+Formula.addClause(negLit(Var), posLit(LeftSubVar), 
posLit(RightSubVar));
+Formula.addClause(posLit(Var), negLit(LeftSubVar));
+Formula.addClause(posLit(Var), negLit(RightSubVar));
+
+// Visit the sub-values of `Val`.
+UnprocessedSubVals.push(>getLeftSubValue());
+UnprocessedSubVals.push(>getRightSubValue());
+  }
 } else 

[clang] c0c9d71 - [clang][dataflow] Rename iterators from IT to It

2022-07-25 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-25T20:28:47+02:00
New Revision: c0c9d717dfd2cbb4d940ce23d20698b4b8f6

URL: 
https://github.com/llvm/llvm-project/commit/c0c9d717dfd2cbb4d940ce23d20698b4b8f6
DIFF: 
https://github.com/llvm/llvm-project/commit/c0c9d717dfd2cbb4d940ce23d20698b4b8f6.diff

LOG: [clang][dataflow] Rename iterators from IT to It

The latter way to abbreviate is a lot more common in the LLVM codebase.

Reviewed By: sgatev, xazax.hun

Differential Revision: https://reviews.llvm.org/D130423

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

Removed: 




diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 5105999741e6a..8f2296dc7e2cc 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -199,18 +199,18 @@ void 
DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
   if (!Res.second)
 return;
 
-  auto ConstraintsIT = FlowConditionConstraints.find();
-  if (ConstraintsIT == FlowConditionConstraints.end()) {
+  auto ConstraintsIt = FlowConditionConstraints.find();
+  if (ConstraintsIt == FlowConditionConstraints.end()) {
 Constraints.insert();
   } else {
 // Bind flow condition token via `iff` to its set of constraints:
 // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints
-Constraints.insert((Token, *ConstraintsIT->second));
+Constraints.insert((Token, *ConstraintsIt->second));
   }
 
-  auto DepsIT = FlowConditionDeps.find();
-  if (DepsIT != FlowConditionDeps.end()) {
-for (AtomicBoolValue *DepToken : DepsIT->second) {
+  auto DepsIt = FlowConditionDeps.find();
+  if (DepsIt != FlowConditionDeps.end()) {
+for (AtomicBoolValue *DepToken : DepsIt->second) {
   addTransitiveFlowConditionConstraints(*DepToken, Constraints,
 VisitedTokens);
 }
@@ -220,10 +220,10 @@ void 
DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
 BoolValue ::substituteBoolValue(
 BoolValue ,
 llvm::DenseMap ) {
-  auto IT = SubstitutionsCache.find();
-  if (IT != SubstitutionsCache.end()) {
+  auto It = SubstitutionsCache.find();
+  if (It != SubstitutionsCache.end()) {
 // Return memoized result of substituting this boolean value.
-return *IT->second;
+return *It->second;
   }
 
   // Handle substitution on the boolean value (and its subvalues), saving the
@@ -280,19 +280,19 @@ BoolValue 
::buildAndSubstituteFlowCondition(
 BoolValue ::buildAndSubstituteFlowConditionWithCache(
 AtomicBoolValue ,
 llvm::DenseMap ) {
-  auto ConstraintsIT = FlowConditionConstraints.find();
-  if (ConstraintsIT == FlowConditionConstraints.end()) {
+  auto ConstraintsIt = FlowConditionConstraints.find();
+  if (ConstraintsIt == FlowConditionConstraints.end()) {
 return getBoolLiteralValue(true);
   }
-  auto DepsIT = FlowConditionDeps.find();
-  if (DepsIT != FlowConditionDeps.end()) {
-for (AtomicBoolValue *DepToken : DepsIT->second) {
+  auto DepsIt = FlowConditionDeps.find();
+  if (DepsIt != FlowConditionDeps.end()) {
+for (AtomicBoolValue *DepToken : DepsIt->second) {
   auto  = buildAndSubstituteFlowConditionWithCache(
   *DepToken, SubstitutionsCache);
   SubstitutionsCache[DepToken] = 
 }
   }
-  return substituteBoolValue(*ConstraintsIT->second, SubstitutionsCache);
+  return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache);
 }
 
 void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue ) {

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 2b6cd0c4f8571..d1af293a9b3e4 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -352,16 +352,16 @@ void Environment::setValue(const StorageLocation , 
Value ) {
 }
   }
 
-  auto IT = MemberLocToStruct.find();
-  if (IT != MemberLocToStruct.end()) {
+  auto It = MemberLocToStruct.find();
+  if (It != MemberLocToStruct.end()) {
 // `Loc` is the location of a struct member so we need to also update the
 // value of the member in the corresponding `StructValue`.
 
-assert(IT->second.first != nullptr);
-StructValue  = *IT->second.first;
+assert(It->second.first != nullptr);
+StructValue  = *It->second.first;
 
-assert(IT->second.second != nullptr);
-const ValueDecl  = *IT->second.second;
+assert(It->second.second != nullptr);
+const ValueDecl  = *It->second.second;
 
 StructVal.setChild(Member, Val);
   }

diff 

[clang] cd9a5cf - Use the range-based overload of llvm::sort where possible

2022-07-23 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-23T15:13:25+02:00
New Revision: cd9a5cfd2e4e4d583c9bf5ef1100acaf5e96f29e

URL: 
https://github.com/llvm/llvm-project/commit/cd9a5cfd2e4e4d583c9bf5ef1100acaf5e96f29e
DIFF: 
https://github.com/llvm/llvm-project/commit/cd9a5cfd2e4e4d583c9bf5ef1100acaf5e96f29e.diff

LOG: Use the range-based overload of llvm::sort where possible

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D130403

Added: 


Modified: 
clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
clang-tools-extra/clangd/index/StdLib.cpp
clang/include/clang/Basic/Attr.td
clang/lib/Driver/Multilib.cpp
clang/lib/Frontend/FrontendAction.cpp
clang/lib/Sema/AnalysisBasedWarnings.cpp
lldb/source/Interpreter/OptionValueArray.cpp
lldb/source/Interpreter/OptionValueFileSpecList.cpp
lldb/source/Interpreter/OptionValuePathMappings.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
lldb/source/Symbol/ArmUnwindInfo.cpp
lldb/source/Symbol/CompileUnit.cpp
lldb/source/Symbol/Symtab.cpp
lldb/source/Target/DynamicRegisterInfo.cpp
lldb/source/Target/Target.cpp
lldb/source/Utility/ReproducerProvider.cpp
lldb/source/Utility/Timer.cpp
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
llvm/unittests/ADT/SmallPtrSetTest.cpp
llvm/unittests/TextAPI/TextStubV1Tests.cpp
llvm/unittests/TextAPI/TextStubV2Tests.cpp
llvm/unittests/TextAPI/TextStubV3Tests.cpp
llvm/unittests/TextAPI/TextStubV4Tests.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp 
b/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
index e25c8e2449dc8..cb5caf1ca92a1 100644
--- 
a/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
+++ 
b/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
@@ -193,8 +193,7 @@ groupReplacements(const TUReplacements , const 
TUDiagnostics ,
   // Sort replacements per file to keep consistent behavior when
   // clang-apply-replacements run on 
diff erents machine.
   for (auto  : GroupedReplacements) {
-llvm::sort(FileAndReplacements.second.begin(),
-   FileAndReplacements.second.end());
+llvm::sort(FileAndReplacements.second);
   }
 
   return GroupedReplacements;

diff  --git a/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp 
b/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
index ebb4a70c1f8db..95b5ed0a8b1aa 100644
--- a/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
+++ b/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
@@ -59,7 +59,7 @@ static void rank(std::vector ,
   }
   // Sort by the gathered scores. Use file name as a tie breaker so we can
   // deduplicate.
-  llvm::sort(Symbols.begin(), Symbols.end(),
+  llvm::sort(Symbols,
  [&](const SymbolAndSignals , const SymbolAndSignals ) {
auto AS = Score[A.Symbol.getFilePath()];
auto BS = Score[B.Symbol.getFilePath()];

diff  --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
index 0209071af87f4..1d15ae19ead4d 100644
--- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
@@ -104,10 +104,8 @@ MagicNumbersCheck::MagicNumbersCheck(StringRef Name, 
ClangTidyContext *Context)
   consumeError(StatusOrErr.takeError());
   IgnoredDoublePointValues.push_back(DoubleValue.convertToDouble());
 }
-llvm::sort(IgnoredFloatingPointValues.begin(),
-   IgnoredFloatingPointValues.end());
-llvm::sort(IgnoredDoublePointValues.begin(),
-   IgnoredDoublePointValues.end());
+llvm::sort(IgnoredFloatingPointValues);
+llvm::sort(IgnoredDoublePointValues);
   }
 }
 

diff  --git a/clang-tools-extra/clangd/index/StdLib.cpp 
b/clang-tools-extra/clangd/index/StdLib.cpp
index f00067229a860..f2edc514bae30 100644
--- a/clang-tools-extra/clangd/index/StdLib.cpp
+++ b/clang-tools-extra/clangd/index/StdLib.cpp
@@ -80,7 +80,7 @@ std::string buildUmbrella(llvm::StringLiteral Mandatory,
   "#endif\n",
   Mandatory);
 
-  llvm::sort(Headers.begin(), Headers.end());
+  llvm::sort(Headers);
   auto Last = std::unique(Headers.begin(), Headers.end());
   for (auto Header = Headers.begin(); Header != Last; ++Header) {
 OS << llvm::formatv("#if __has_include({0})\n"

diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 78e0fce917a0f..d61f3583281d1 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2703,7 +2703,7 @@ def 

[clang-tools-extra] cd9a5cf - Use the range-based overload of llvm::sort where possible

2022-07-23 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-23T15:13:25+02:00
New Revision: cd9a5cfd2e4e4d583c9bf5ef1100acaf5e96f29e

URL: 
https://github.com/llvm/llvm-project/commit/cd9a5cfd2e4e4d583c9bf5ef1100acaf5e96f29e
DIFF: 
https://github.com/llvm/llvm-project/commit/cd9a5cfd2e4e4d583c9bf5ef1100acaf5e96f29e.diff

LOG: Use the range-based overload of llvm::sort where possible

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D130403

Added: 


Modified: 
clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
clang-tools-extra/clangd/index/StdLib.cpp
clang/include/clang/Basic/Attr.td
clang/lib/Driver/Multilib.cpp
clang/lib/Frontend/FrontendAction.cpp
clang/lib/Sema/AnalysisBasedWarnings.cpp
lldb/source/Interpreter/OptionValueArray.cpp
lldb/source/Interpreter/OptionValueFileSpecList.cpp
lldb/source/Interpreter/OptionValuePathMappings.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
lldb/source/Symbol/ArmUnwindInfo.cpp
lldb/source/Symbol/CompileUnit.cpp
lldb/source/Symbol/Symtab.cpp
lldb/source/Target/DynamicRegisterInfo.cpp
lldb/source/Target/Target.cpp
lldb/source/Utility/ReproducerProvider.cpp
lldb/source/Utility/Timer.cpp
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
llvm/unittests/ADT/SmallPtrSetTest.cpp
llvm/unittests/TextAPI/TextStubV1Tests.cpp
llvm/unittests/TextAPI/TextStubV2Tests.cpp
llvm/unittests/TextAPI/TextStubV3Tests.cpp
llvm/unittests/TextAPI/TextStubV4Tests.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp 
b/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
index e25c8e2449dc8..cb5caf1ca92a1 100644
--- 
a/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
+++ 
b/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
@@ -193,8 +193,7 @@ groupReplacements(const TUReplacements , const 
TUDiagnostics ,
   // Sort replacements per file to keep consistent behavior when
   // clang-apply-replacements run on 
diff erents machine.
   for (auto  : GroupedReplacements) {
-llvm::sort(FileAndReplacements.second.begin(),
-   FileAndReplacements.second.end());
+llvm::sort(FileAndReplacements.second);
   }
 
   return GroupedReplacements;

diff  --git a/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp 
b/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
index ebb4a70c1f8db..95b5ed0a8b1aa 100644
--- a/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
+++ b/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp
@@ -59,7 +59,7 @@ static void rank(std::vector ,
   }
   // Sort by the gathered scores. Use file name as a tie breaker so we can
   // deduplicate.
-  llvm::sort(Symbols.begin(), Symbols.end(),
+  llvm::sort(Symbols,
  [&](const SymbolAndSignals , const SymbolAndSignals ) {
auto AS = Score[A.Symbol.getFilePath()];
auto BS = Score[B.Symbol.getFilePath()];

diff  --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
index 0209071af87f4..1d15ae19ead4d 100644
--- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
@@ -104,10 +104,8 @@ MagicNumbersCheck::MagicNumbersCheck(StringRef Name, 
ClangTidyContext *Context)
   consumeError(StatusOrErr.takeError());
   IgnoredDoublePointValues.push_back(DoubleValue.convertToDouble());
 }
-llvm::sort(IgnoredFloatingPointValues.begin(),
-   IgnoredFloatingPointValues.end());
-llvm::sort(IgnoredDoublePointValues.begin(),
-   IgnoredDoublePointValues.end());
+llvm::sort(IgnoredFloatingPointValues);
+llvm::sort(IgnoredDoublePointValues);
   }
 }
 

diff  --git a/clang-tools-extra/clangd/index/StdLib.cpp 
b/clang-tools-extra/clangd/index/StdLib.cpp
index f00067229a860..f2edc514bae30 100644
--- a/clang-tools-extra/clangd/index/StdLib.cpp
+++ b/clang-tools-extra/clangd/index/StdLib.cpp
@@ -80,7 +80,7 @@ std::string buildUmbrella(llvm::StringLiteral Mandatory,
   "#endif\n",
   Mandatory);
 
-  llvm::sort(Headers.begin(), Headers.end());
+  llvm::sort(Headers);
   auto Last = std::unique(Headers.begin(), Headers.end());
   for (auto Header = Headers.begin(); Header != Last; ++Header) {
 OS << llvm::formatv("#if __has_include({0})\n"

diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 78e0fce917a0f..d61f3583281d1 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2703,7 +2703,7 @@ def 

[clang] b5414b5 - [clang][dataflow] Add DataflowEnvironment::dump()

2022-07-22 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-23T01:31:53+02:00
New Revision: b5414b566a5aedd90e41f01dd2b7b632afc5d5b7

URL: 
https://github.com/llvm/llvm-project/commit/b5414b566a5aedd90e41f01dd2b7b632afc5d5b7
DIFF: 
https://github.com/llvm/llvm-project/commit/b5414b566a5aedd90e41f01dd2b7b632afc5d5b7.diff

LOG: [clang][dataflow] Add DataflowEnvironment::dump()

Start by dumping the flow condition.

Reviewed By: ymandel

Differential Revision: https://reviews.llvm.org/D130398

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 358ace0430f62..abc3183e1b0b5 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -23,6 +23,7 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/Compiler.h"
 #include 
 #include 
 #include 
@@ -251,6 +252,8 @@ class DataflowAnalysisContext {
   /// `Val2` imposed by the flow condition.
   bool equivalentBoolValues(BoolValue , BoolValue );
 
+  LLVM_DUMP_METHOD void dumpFlowCondition(AtomicBoolValue );
+
 private:
   struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo {
 static QualType getEmptyKey() {

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index ce195f0662f53..f17df36f6a4a3 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -19,7 +19,6 @@
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
-#include "clang/AST/TypeOrdering.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
@@ -325,6 +324,8 @@ class Environment {
   /// imply that `Val` is true.
   bool flowConditionImplies(BoolValue ) const;
 
+  LLVM_DUMP_METHOD void dump() const;
+
 private:
   /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
   /// return null.

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h 
b/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
index 74367d29b2a0f..b8efdeb61d280 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
@@ -42,6 +42,20 @@ std::string debugString(
 const BoolValue ,
 llvm::DenseMap AtomNames = {{}});
 
+/// Returns a string representation for `Constraints` - a collection of boolean
+/// formulas.
+///
+/// Atomic booleans appearing in the boolean value `Constraints` are assigned 
to
+/// labels either specified in `AtomNames` or created by default rules as B0,
+/// B1, ...
+///
+/// Requirements:
+///
+///   Names assigned to atoms should not be repeated in `AtomNames`.
+std::string debugString(
+const llvm::DenseSet ,
+llvm::DenseMap AtomNames = {{}});
+
 /// Returns a string representation for `Constraints` - a collection of boolean
 /// formulas and the `Result` of satisfiability checking.
 ///

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index cd87e87a6acab..5105999741e6a 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -14,7 +14,9 @@
 
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/Analysis/FlowSensitive/DebugSupport.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
+#include "llvm/Support/Debug.h"
 #include 
 #include 
 #include 
@@ -293,6 +295,17 @@ BoolValue 
::buildAndSubstituteFlowConditionWithCache(
   return substituteBoolValue(*ConstraintsIT->second, SubstitutionsCache);
 }
 
+void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue ) {
+  llvm::DenseSet Constraints = {};
+  llvm::DenseSet VisitedTokens;
+  addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
+
+  llvm::DenseMap AtomNames = {
+  {(false), "False"},
+  {(true), "True"}};
+  llvm::dbgs() << 

[clang] ee6aba8 - [clang][dataflow] Expose stringification functions for SAT solver enums

2022-07-22 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-23T01:21:20+02:00
New Revision: ee6aba85aa48d03a931ba989ea2c1584b468588a

URL: 
https://github.com/llvm/llvm-project/commit/ee6aba85aa48d03a931ba989ea2c1584b468588a
DIFF: 
https://github.com/llvm/llvm-project/commit/ee6aba85aa48d03a931ba989ea2c1584b468588a.diff

LOG: [clang][dataflow] Expose stringification functions for SAT solver enums

Reviewed By: ymandel

Differential Revision: https://reviews.llvm.org/D130399

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
clang/lib/Analysis/FlowSensitive/DebugSupport.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h 
b/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
index 3b854850907b..74367d29b2a0 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
@@ -23,6 +23,13 @@
 
 namespace clang {
 namespace dataflow {
+
+/// Returns a string representation of a boolean assignment to true or false.
+std::string debugString(Solver::Result::Assignment Assignment);
+
+/// Returns a string representation of the result status of a SAT check.
+std::string debugString(Solver::Result::Status Status);
+
 /// Returns a string representation for the boolean value `B`.
 ///
 /// Atomic booleans appearing in the boolean value `B` are assigned to labels

diff  --git a/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp 
b/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
index 1d699a9c9804..f4217fd04c49 100644
--- a/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
@@ -30,6 +30,28 @@ using llvm::AlignStyle;
 using llvm::fmt_pad;
 using llvm::formatv;
 
+std::string debugString(Solver::Result::Assignment Assignment) {
+  switch (Assignment) {
+  case Solver::Result::Assignment::AssignedFalse:
+return "False";
+  case Solver::Result::Assignment::AssignedTrue:
+return "True";
+  }
+  llvm_unreachable("Booleans can only be assigned true/false");
+}
+
+std::string debugString(Solver::Result::Status Status) {
+  switch (Status) {
+  case Solver::Result::Status::Satisfiable:
+return "Satisfiable";
+  case Solver::Result::Status::Unsatisfiable:
+return "Unsatisfiable";
+  case Solver::Result::Status::TimedOut:
+return "TimedOut";
+  }
+  llvm_unreachable("Unhandled SAT check result status");
+}
+
 namespace {
 
 class DebugStringGenerator {
@@ -101,7 +123,7 @@ Constraints
   ConstraintsStrings.push_back(debugString(*Constraint));
 }
 
-auto StatusString = debugString(Result.getStatus());
+auto StatusString = clang::dataflow::debugString(Result.getStatus());
 auto Solution = Result.getSolution();
 auto SolutionString = Solution ? "\n" + debugString(Solution.value()) : "";
 
@@ -126,7 +148,7 @@ Constraints
   auto Line = formatv("{0} = {1}",
   fmt_align(getAtomName(AtomAssignment.first),
 AlignStyle::Left, MaxNameLength),
-  debugString(AtomAssignment.second));
+  clang::dataflow::debugString(AtomAssignment.second));
   Lines.push_back(Line);
 }
 llvm::sort(Lines.begin(), Lines.end());
@@ -134,30 +156,6 @@ Constraints
 return formatv("{0:$[\n]}", llvm::make_range(Lines.begin(), Lines.end()));
   }
 
-  /// Returns a string representation of a boolean assignment to true or false.
-  std::string debugString(Solver::Result::Assignment Assignment) {
-switch (Assignment) {
-case Solver::Result::Assignment::AssignedFalse:
-  return "False";
-case Solver::Result::Assignment::AssignedTrue:
-  return "True";
-}
-llvm_unreachable("Booleans can only be assigned true/false");
-  }
-
-  /// Returns a string representation of the result status of a SAT check.
-  std::string debugString(Solver::Result::Status Status) {
-switch (Status) {
-case Solver::Result::Status::Satisfiable:
-  return "Satisfiable";
-case Solver::Result::Status::Unsatisfiable:
-  return "Unsatisfiable";
-case Solver::Result::Status::TimedOut:
-  return "TimedOut";
-}
-llvm_unreachable("Unhandled SAT check result status");
-  }
-
   /// Returns the name assigned to `Atom`, either user-specified or created by
   /// default rules (B0, B1, ...).
   std::string getAtomName(const AtomicBoolValue *Atom) {



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


[clang] 589ddd7 - [clang][dataflow] ArrayRef'ize debugString()

2022-07-22 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-23T01:16:31+02:00
New Revision: 589ddd7fe8e4dcf3323dd0b8f6af3ae953ed6037

URL: 
https://github.com/llvm/llvm-project/commit/589ddd7fe8e4dcf3323dd0b8f6af3ae953ed6037
DIFF: 
https://github.com/llvm/llvm-project/commit/589ddd7fe8e4dcf3323dd0b8f6af3ae953ed6037.diff

LOG: [clang][dataflow] ArrayRef'ize debugString()

Reviewed By: ymandel

Differential Revision: https://reviews.llvm.org/D130400

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
clang/lib/Analysis/FlowSensitive/DebugSupport.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h 
b/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
index ef903d807e12f..3b854850907b5 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h
@@ -46,7 +46,7 @@ std::string debugString(
 ///
 ///   Names assigned to atoms should not be repeated in `AtomNames`.
 std::string debugString(
-const std::vector , const Solver::Result ,
+ArrayRef Constraints, const Solver::Result ,
 llvm::DenseMap AtomNames = {{}});
 inline std::string debugString(
 const llvm::DenseSet ,

diff  --git a/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp 
b/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
index a2895d0197b1d..1d699a9c98040 100644
--- a/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
@@ -82,7 +82,7 @@ class DebugStringGenerator {
 
   /// Returns a string representation of a set of boolean `Constraints` and the
   /// `Result` of satisfiability checking on the `Constraints`.
-  std::string debugString(const std::vector ,
+  std::string debugString(ArrayRef ,
   const Solver::Result ) {
 auto Template = R"(
 Constraints
@@ -185,8 +185,7 @@ debugString(const BoolValue ,
 }
 
 std::string
-debugString(const std::vector ,
-const Solver::Result ,
+debugString(ArrayRef Constraints, const Solver::Result ,
 llvm::DenseMap AtomNames) {
   return DebugStringGenerator(std::move(AtomNames))
   .debugString(Constraints, Result);



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


[clang] 63fac42 - Revert "[clang][dataflow] Return a solution from the solver when `Constraints` are `Satisfiable`."

2022-07-07 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-07T21:50:52+02:00
New Revision: 63fac424e674bbd77f63e2c76cda9ae28552916a

URL: 
https://github.com/llvm/llvm-project/commit/63fac424e674bbd77f63e2c76cda9ae28552916a
DIFF: 
https://github.com/llvm/llvm-project/commit/63fac424e674bbd77f63e2c76cda9ae28552916a.diff

LOG: Revert "[clang][dataflow] Return a solution from the solver when 
`Constraints` are `Satisfiable`."

This reverts commit 19e21887eb18aa019000c2384ea7f2c91d937489. I
accidentally landed the non-final version of the patch that used
decomposition declarations (not yet usable in LLVM/Clang source).

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/Solver.h
clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
clang/unittests/Analysis/FlowSensitive/SolverTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 358ace0430f62..d87b9cc37b996 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -271,18 +271,17 @@ class DataflowAnalysisContext {
   AtomicBoolValue , llvm::DenseSet ,
   llvm::DenseSet );
 
-  /// Returns the outcome of satisfiability checking on `Constraints`.
-  /// Possible outcomes are:
-  /// - `Satisfiable`: A satisfying assignment exists and is returned.
-  /// - `Unsatisfiable`: A satisfying assignment does not exist.
-  /// - `TimedOut`: The search for a satisfying assignment was not completed.
+  /// Returns the result of satisfiability checking on `Constraints`.
+  /// Possible return values are:
+  /// - `Satisfiable`: There exists a satisfying assignment for `Constraints`.
+  /// - `Unsatisfiable`: There is no satisfying assignment for `Constraints`.
+  /// - `TimedOut`: The solver gives up on finding a satisfying assignment.
   Solver::Result querySolver(llvm::DenseSet Constraints);
 
   /// Returns true if the solver is able to prove that there is no satisfying
   /// assignment for `Constraints`
   bool isUnsatisfiable(llvm::DenseSet Constraints) {
-return querySolver(std::move(Constraints)).getStatus() ==
-   Solver::Result::Status::Unsatisfiable;
+return querySolver(std::move(Constraints)) == 
Solver::Result::Unsatisfiable;
   }
 
   /// Returns a boolean value as a result of substituting `Val` and its sub

diff  --git a/clang/include/clang/Analysis/FlowSensitive/Solver.h 
b/clang/include/clang/Analysis/FlowSensitive/Solver.h
index b7a14f3484e42..6b685b9b3c9a7 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Solver.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Solver.h
@@ -15,9 +15,7 @@
 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H
 
 #include "clang/Analysis/FlowSensitive/Value.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
 
 namespace clang {
 namespace dataflow {
@@ -25,58 +23,17 @@ namespace dataflow {
 /// An interface for a SAT solver that can be used by dataflow analyses.
 class Solver {
 public:
-  struct Result {
-enum class Status {
-  /// Indicates that there exists a satisfying assignment for a boolean
-  /// formula.
-  Satisfiable,
-
-  /// Indicates that there is no satisfying assignment for a boolean
-  /// formula.
-  Unsatisfiable,
-
-  /// Indicates that the solver gave up trying to find a satisfying
-  /// assignment for a boolean formula.
-  TimedOut,
-};
-
-/// A boolean value is set to true or false in a truth assignment.
-enum class Assignment : uint8_t { AssignedFalse = 0, AssignedTrue = 1 };
-
-/// Constructs a result indicating that the queried boolean formula is
-/// satisfiable. The result will hold a solution found by the solver.
-static Result
-Satisfiable(llvm::DenseMap Solution) {
-  return Result(Status::Satisfiable, std::move(Solution));
-}
-
-/// Constructs a result indicating that the queried boolean formula is
-/// unsatisfiable.
-static Result Unsatisfiable() { return Result(Status::Unsatisfiable, {}); }
-
-/// Constructs a result indicating that satisfiability checking on the
-/// queried boolean formula was not completed.
-static Result TimedOut() { return Result(Status::TimedOut, {}); }
-
-/// Returns the status of satisfiability checking on the queried boolean
+  enum class Result {
+/// Indicates that there exists a satisfying assignment for a boolean
 /// formula.
-Status getStatus() const { return Status; }
+Satisfiable,
 
-/// Returns a truth assignment to boolean values that satisfies the queried
-/// boolean formula if available. Otherwise, an empty optional is returned.
-llvm::Optional>
-  

[clang] 19e2188 - [clang][dataflow] Return a solution from the solver when `Constraints` are `Satisfiable`.

2022-07-07 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-07-07T20:53:47+02:00
New Revision: 19e21887eb18aa019000c2384ea7f2c91d937489

URL: 
https://github.com/llvm/llvm-project/commit/19e21887eb18aa019000c2384ea7f2c91d937489
DIFF: 
https://github.com/llvm/llvm-project/commit/19e21887eb18aa019000c2384ea7f2c91d937489.diff

LOG: [clang][dataflow] Return a solution from the solver when `Constraints` are 
`Satisfiable`.

A truth assignment to atomic boolean values which satisfy `Constraints` will be 
returned if found by the solver.
This gives us more information which can be helpful for debugging or 
constructing warning messages.

Reviewed By: hlopko, gribozavr2, sgatev

Differential Revision: https://reviews.llvm.org/D129180

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/Solver.h
clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
clang/unittests/Analysis/FlowSensitive/SolverTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index d87b9cc37b996..358ace0430f62 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -271,17 +271,18 @@ class DataflowAnalysisContext {
   AtomicBoolValue , llvm::DenseSet ,
   llvm::DenseSet );
 
-  /// Returns the result of satisfiability checking on `Constraints`.
-  /// Possible return values are:
-  /// - `Satisfiable`: There exists a satisfying assignment for `Constraints`.
-  /// - `Unsatisfiable`: There is no satisfying assignment for `Constraints`.
-  /// - `TimedOut`: The solver gives up on finding a satisfying assignment.
+  /// Returns the outcome of satisfiability checking on `Constraints`.
+  /// Possible outcomes are:
+  /// - `Satisfiable`: A satisfying assignment exists and is returned.
+  /// - `Unsatisfiable`: A satisfying assignment does not exist.
+  /// - `TimedOut`: The search for a satisfying assignment was not completed.
   Solver::Result querySolver(llvm::DenseSet Constraints);
 
   /// Returns true if the solver is able to prove that there is no satisfying
   /// assignment for `Constraints`
   bool isUnsatisfiable(llvm::DenseSet Constraints) {
-return querySolver(std::move(Constraints)) == 
Solver::Result::Unsatisfiable;
+return querySolver(std::move(Constraints)).getStatus() ==
+   Solver::Result::Status::Unsatisfiable;
   }
 
   /// Returns a boolean value as a result of substituting `Val` and its sub

diff  --git a/clang/include/clang/Analysis/FlowSensitive/Solver.h 
b/clang/include/clang/Analysis/FlowSensitive/Solver.h
index 6b685b9b3c9a7..b7a14f3484e42 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Solver.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Solver.h
@@ -15,7 +15,9 @@
 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H
 
 #include "clang/Analysis/FlowSensitive/Value.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
 
 namespace clang {
 namespace dataflow {
@@ -23,17 +25,58 @@ namespace dataflow {
 /// An interface for a SAT solver that can be used by dataflow analyses.
 class Solver {
 public:
-  enum class Result {
-/// Indicates that there exists a satisfying assignment for a boolean
+  struct Result {
+enum class Status {
+  /// Indicates that there exists a satisfying assignment for a boolean
+  /// formula.
+  Satisfiable,
+
+  /// Indicates that there is no satisfying assignment for a boolean
+  /// formula.
+  Unsatisfiable,
+
+  /// Indicates that the solver gave up trying to find a satisfying
+  /// assignment for a boolean formula.
+  TimedOut,
+};
+
+/// A boolean value is set to true or false in a truth assignment.
+enum class Assignment : uint8_t { AssignedFalse = 0, AssignedTrue = 1 };
+
+/// Constructs a result indicating that the queried boolean formula is
+/// satisfiable. The result will hold a solution found by the solver.
+static Result
+Satisfiable(llvm::DenseMap Solution) {
+  return Result(Status::Satisfiable, std::move(Solution));
+}
+
+/// Constructs a result indicating that the queried boolean formula is
+/// unsatisfiable.
+static Result Unsatisfiable() { return Result(Status::Unsatisfiable, {}); }
+
+/// Constructs a result indicating that satisfiability checking on the
+/// queried boolean formula was not completed.
+static Result TimedOut() { return Result(Status::TimedOut, {}); }
+
+/// Returns the status of satisfiability checking on the queried boolean
 /// formula.
-Satisfiable,
+Status getStatus() const { return Status; }
 
-/// Indicates that there is no satisfying assignment for a boolean formula.

[clang-tools-extra] 40af95d - [clang-tools-extra] Fix a link in ReleaseNotes.rst

2022-07-05 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-05T23:09:55+02:00
New Revision: 40af95d80bcb526ec7b025eb677f64bfdd083e96

URL: 
https://github.com/llvm/llvm-project/commit/40af95d80bcb526ec7b025eb677f64bfdd083e96
DIFF: 
https://github.com/llvm/llvm-project/commit/40af95d80bcb526ec7b025eb677f64bfdd083e96.diff

LOG: [clang-tools-extra] Fix a link in ReleaseNotes.rst

Added: 


Modified: 
clang-tools-extra/docs/ReleaseNotes.rst

Removed: 




diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index ff444a0934f6f..1d6fd05605db7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -133,7 +133,7 @@ New checks
   Detects confusable Unicode identifiers.
 
 - New :doc:`bugprone-assignment-in-if-condition
-  ` check.
+  ` check.
 
   Warns when there is an assignment within an if statement condition 
expression.
 



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


[clang-tools-extra] 05130a6 - new clang-tidy checker for assignments within condition clause of if statement

2022-07-05 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-07-05T23:04:12+02:00
New Revision: 05130a6ba7d9974136388c1fbe63125596325d2e

URL: 
https://github.com/llvm/llvm-project/commit/05130a6ba7d9974136388c1fbe63125596325d2e
DIFF: 
https://github.com/llvm/llvm-project/commit/05130a6ba7d9974136388c1fbe63125596325d2e.diff

LOG: new clang-tidy checker for assignments within condition clause of if 
statement

new clang-tidy checker for assignments within the condition clause of an 'if' 
statement.

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D127114

Added: 
clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp
clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.h

clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-if-condition.rst

clang-tools-extra/test/clang-tidy/checkers/bugprone-assignment-in-if-condition.cpp

Modified: 
clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp
new file mode 100644
index 0..e4f52191e0b00
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp
@@ -0,0 +1,49 @@
+//===--- AssignmentInIfConditionCheck.cpp - clang-tidy 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "AssignmentInIfConditionCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void AssignmentInIfConditionCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(ifStmt(hasCondition(forEachDescendant(
+ binaryOperator(isAssignmentOperator())
+ .bind("assignment_in_if_statement",
+ this);
+  Finder->addMatcher(ifStmt(hasCondition(forEachDescendant(
+ cxxOperatorCallExpr(isAssignmentOperator())
+ .bind("assignment_in_if_statement",
+ this);
+}
+
+void AssignmentInIfConditionCheck::check(
+const MatchFinder::MatchResult ) {
+  const auto *MatchedDecl =
+  Result.Nodes.getNodeAs("assignment_in_if_statement");
+  if (!MatchedDecl) {
+return;
+  }
+  diag(MatchedDecl->getBeginLoc(),
+   "an assignment within an 'if' condition is bug-prone");
+  diag(MatchedDecl->getBeginLoc(),
+   "if it should be an assignment, move it out of the 'if' condition",
+   DiagnosticIDs::Note);
+  diag(MatchedDecl->getBeginLoc(),
+   "if it is meant to be an equality check, change '=' to '=='",
+   DiagnosticIDs::Note);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang

diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.h 
b/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.h
new file mode 100644
index 0..8e57f1a7ca80d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.h
@@ -0,0 +1,34 @@
+//===--- AssignmentInIfConditionCheck.h - clang-tidy *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSIGNMENTINIFCONDITIONCHECK_H
+#define 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSIGNMENTINIFCONDITIONCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Catches assignments within the condition clause of an if statement.
+///
+/// For the user-facing documentation see:
+/// 
http://clang.llvm.org/extra/clang-tidy/checks/bugprone-assignment-in-if-condition.html
+class AssignmentInIfConditionCheck : public ClangTidyCheck {
+public:
+  AssignmentInIfConditionCheck(StringRef Name, ClangTidyContext *Context)
+  : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult ) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // 

[clang] ae90bc8 - [clang][dataflow] Add `buildAndSubstituteFlowCondition` to `DataflowEnvironment`

2022-06-27 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-27T21:09:05+02:00
New Revision: ae90bc8467589cbc2079b93fae2b6ceec0821e27

URL: 
https://github.com/llvm/llvm-project/commit/ae90bc8467589cbc2079b93fae2b6ceec0821e27
DIFF: 
https://github.com/llvm/llvm-project/commit/ae90bc8467589cbc2079b93fae2b6ceec0821e27.diff

LOG: [clang][dataflow] Add `buildAndSubstituteFlowCondition` to 
`DataflowEnvironment`

Depends On D128658

Reviewed By: gribozavr2, xazax.hun

Differential Revision: https://reviews.llvm.org/D128659

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 302e35d337e64..ce195f0662f53 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -308,6 +308,16 @@ class Environment {
   /// Returns the token that identifies the flow condition of the environment.
   AtomicBoolValue () const { return *FlowConditionToken; 
}
 
+  /// Builds and returns the logical formula defining the flow condition
+  /// identified by `Token`. If a value in the formula is present as a key in
+  /// `Substitutions`, it will be substituted with the value it maps to.
+  BoolValue (
+  AtomicBoolValue ,
+  llvm::DenseMap Substitutions) {
+return DACtx->buildAndSubstituteFlowCondition(Token,
+  std::move(Substitutions));
+  }
+
   /// Adds `Val` to the set of clauses that constitute the flow condition.
   void addToFlowCondition(BoolValue );
 



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


[clang] fa34210 - [clang][dataflow] Do not allow substitution of true/false boolean literals in `buildAndSubstituteFlowCondition`

2022-06-27 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-27T21:04:52+02:00
New Revision: fa34210fa69f64a96dc64983b3de00ddd21e55e1

URL: 
https://github.com/llvm/llvm-project/commit/fa34210fa69f64a96dc64983b3de00ddd21e55e1
DIFF: 
https://github.com/llvm/llvm-project/commit/fa34210fa69f64a96dc64983b3de00ddd21e55e1.diff

LOG: [clang][dataflow] Do not allow substitution of true/false boolean literals 
in `buildAndSubstituteFlowCondition`

Reviewed By: gribozavr2, xazax.hun

Differential Revision: https://reviews.llvm.org/D128658

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp

Removed: 




diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 4c7f0d1f94fa7..e08fc71c51dc7 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -220,8 +220,12 @@ BoolValue ::substituteBoolValue(
 llvm::DenseMap ) {
   auto IT = SubstitutionsCache.find();
   if (IT != SubstitutionsCache.end()) {
+// Return memoized result of substituting this boolean value.
 return *IT->second;
   }
+
+  // Handle substitution on the boolean value (and its subvalues), saving the
+  // result into `SubstitutionsCache`.
   BoolValue *Result;
   switch (Val.getKind()) {
   case Value::Kind::AtomicBool: {
@@ -262,6 +266,10 @@ BoolValue ::substituteBoolValue(
 BoolValue ::buildAndSubstituteFlowCondition(
 AtomicBoolValue ,
 llvm::DenseMap Substitutions) {
+  assert(
+  Substitutions.find((true)) == Substitutions.end() &&
+  Substitutions.find((false)) == Substitutions.end() &&
+  "Do not substitute true/false boolean literals");
   llvm::DenseMap SubstitutionsCache(
   Substitutions.begin(), Substitutions.end());
   return buildAndSubstituteFlowConditionWithCache(Token, SubstitutionsCache);

diff  --git 
a/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
index 26bc37bda617b..758b1a8b21a2b 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
@@ -276,6 +276,34 @@ TEST_F(DataflowAnalysisContextTest, EquivBoolVals) {
   Context.getOrCreateConjunction(X, Context.getOrCreateConjunction(Y, 
Z;
 }
 
+#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
+TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsTrueUnchanged) {
+  auto  = Context.getBoolLiteralValue(true);
+  auto  = Context.createAtomicBoolValue();
+
+  // FC = True
+  auto  = Context.makeFlowConditionToken();
+  Context.addFlowConditionConstraint(FC, True);
+
+  // `True` should never be substituted
+  EXPECT_DEATH(Context.buildAndSubstituteFlowCondition(FC, {{, }}),
+   "Do not substitute true/false boolean literals");
+}
+
+TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsFalseUnchanged) {
+  auto  = Context.getBoolLiteralValue(false);
+  auto  = Context.createAtomicBoolValue();
+
+  // FC = False
+  auto  = Context.makeFlowConditionToken();
+  Context.addFlowConditionConstraint(FC, False);
+
+  // `False` should never be substituted
+  EXPECT_DEATH(Context.buildAndSubstituteFlowCondition(FC, {{, }}),
+   "Do not substitute true/false boolean literals");
+}
+#endif
+
 TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsAtomicFC) {
   auto  = Context.createAtomicBoolValue();
   auto  = Context.getBoolLiteralValue(true);



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


[clang] b611376 - [clang][dataflow] Singleton pointer values for null pointers.

2022-06-27 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-27T14:17:34+02:00
New Revision: b611376e7eb5ea8bd0b32c2911e039b29828b9a8

URL: 
https://github.com/llvm/llvm-project/commit/b611376e7eb5ea8bd0b32c2911e039b29828b9a8
DIFF: 
https://github.com/llvm/llvm-project/commit/b611376e7eb5ea8bd0b32c2911e039b29828b9a8.diff

LOG: [clang][dataflow] Singleton pointer values for null pointers.

When a `nullptr` is assigned to a pointer variable, it is wrapped in a 
`ImplicitCastExpr` with cast kind `CK_NullTo(Member)Pointer`. This patch 
assigns singleton pointer values representing null to these expressions.

For each pointee type, a singleton null `PointerValue` is created and stored in 
the `NullPointerVals` map of the `DataflowAnalysisContext` class. The pointee 
type is retrieved from the implicit cast expression, and used to initialise the 
`PointeeLoc` field of the `PointerValue`. The `PointeeLoc` created is not 
mapped to any `Value`, reflecting the absence of value indicated by null 
pointers.

Reviewed By: gribozavr2, sgatev, xazax.hun

Differential Revision: https://reviews.llvm.org/D128056

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 2e6b8ea7b0da..c1100d8474aa 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -17,6 +17,7 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/TypeOrdering.h"
 #include "clang/Analysis/FlowSensitive/Solver.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
@@ -152,6 +153,10 @@ class DataflowAnalysisContext {
 return ThisPointeeLoc;
   }
 
+  /// Returns a pointer value that represents a null pointer. Calls with
+  /// `PointeeType` that are canonically equivalent will return the same 
result.
+  PointerValue (QualType PointeeType);
+
   /// Returns a symbolic boolean value that models a boolean literal equal to
   /// `Value`.
   AtomicBoolValue (bool Value) const {
@@ -300,6 +305,14 @@ class DataflowAnalysisContext {
 
   StorageLocation *ThisPointeeLoc = nullptr;
 
+  // Null pointer values, keyed by the canonical pointee type.
+  //
+  // FIXME: The pointer values are indexed by the pointee types which are
+  // required to initialize the `PointeeLoc` field in `PointerValue`. Consider
+  // creating a type-independent `NullPointerValue` without a `PointeeLoc`
+  // field.
+  llvm::DenseMap NullPointerVals;
+
   AtomicBoolValue 
   AtomicBoolValue 
 

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index ac49d22995c1..302e35d337e6 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -203,6 +203,10 @@ class Environment {
   /// in the environment.
   StorageLocation *getThisPointeeStorageLocation() const;
 
+  /// Returns a pointer value that represents a null pointer. Calls with
+  /// `PointeeType` that are canonically equivalent will return the same 
result.
+  PointerValue (QualType PointeeType);
+
   /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
   /// return null. If `Type` is a pointer or reference type, creates all the
   /// necessary storage locations and values for indirections until it finds a

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index de48fd71b065..4c7f0d1f94fa 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -55,6 +55,19 @@ DataflowAnalysisContext::getStableStorageLocation(const Expr 
) {
   return Loc;
 }
 
+PointerValue &
+DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) {
+  assert(!PointeeType.isNull());
+  auto CanonicalPointeeType = PointeeType.getCanonicalType();
+  auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
+  if (Res.second) {
+auto  = getStableStorageLocation(CanonicalPointeeType);
+Res.first->second =
+(std::make_unique(PointeeLoc));
+  }
+  return *Res.first->second;
+}
+
 static std::pair
 makeCanonicalBoolValuePair(BoolValue , BoolValue ) {
   auto Res = std::make_pair(, 

[clang] bdfe556 - [clang][dataflow] Implement functionality for flow condition variable substitution.

2022-06-27 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-27T11:37:46+02:00
New Revision: bdfe556dd837007c5671f33384d26e9ea315db53

URL: 
https://github.com/llvm/llvm-project/commit/bdfe556dd837007c5671f33384d26e9ea315db53
DIFF: 
https://github.com/llvm/llvm-project/commit/bdfe556dd837007c5671f33384d26e9ea315db53.diff

LOG: [clang][dataflow] Implement functionality for flow condition variable 
substitution.

This patch introduces `buildAndSubstituteFlowCondition` - given a flow 
condition token, this function returns the expression of constraints defining 
the flow condition, with values substituted where specified.

As an example:
Say we have tokens `FC1`, `FC2`, `FC3`:
```
FlowConditionConstraints: {
 FC1: C1,
 FC2: C2,
 FC3: (FC1 v FC2) ^ C3,
}
```
`buildAndSubstituteFlowCondition(FC3, /*Substitutions:*/{{C1 -> C1'}})`
returns a value corresponding to `(C1' v C2) ^ C3`.

Note:
This function returns the flow condition expressed directly as its constraints, 
which differs to how we currently represent the flow condition as a token bound 
to a set of constraints and dependencies. Making the representation consistent 
may be an option to consider in the future.

Depends On D128357

Reviewed By: gribozavr2, xazax.hun

Differential Revision: https://reviews.llvm.org/D128363

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 58acd5639c436..2e6b8ea7b0da0 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -211,6 +211,27 @@ class DataflowAnalysisContext {
   AtomicBoolValue (AtomicBoolValue ,
   AtomicBoolValue );
 
+  // FIXME: This function returns the flow condition expressed directly as its
+  // constraints: (C1 AND C2 AND ...). This 
diff ers from the general approach in
+  // the framework where a flow condition is represented as a token (an atomic
+  // boolean) with dependencies and constraints tracked in `FlowConditionDeps`
+  // and `FlowConditionConstraints`: (FC <=> C1 AND C2 AND ...).
+  // Consider if we should make the representation of flow condition 
consistent,
+  // returning an atomic boolean token with separate constraints instead.
+  //
+  /// Builds and returns the logical formula defining the flow condition
+  /// identified by `Token`. If a value in the formula is present as a key in
+  /// `Substitutions`, it will be substituted with the value it maps to.
+  /// As an example, say we have flow condition tokens FC1, FC2, FC3 and
+  /// FlowConditionConstraints: { FC1: C1,
+  /// FC2: C2,
+  /// FC3: (FC1 v FC2) ^ C3 }
+  /// buildAndSubstituteFlowCondition(FC3, {{C1 -> C1'}}) will return a value
+  /// corresponding to (C1' v C2) ^ C3.
+  BoolValue (
+  AtomicBoolValue ,
+  llvm::DenseMap Substitutions);
+
   /// Returns true if and only if the constraints of the flow condition
   /// identified by `Token` imply that `Val` is true.
   bool flowConditionImplies(AtomicBoolValue , BoolValue );
@@ -246,6 +267,23 @@ class DataflowAnalysisContext {
 return querySolver(std::move(Constraints)) == 
Solver::Result::Unsatisfiable;
   }
 
+  /// Returns a boolean value as a result of substituting `Val` and its sub
+  /// values based on entries in `SubstitutionsCache`. Intermediate results are
+  /// stored in `SubstitutionsCache` to avoid reprocessing values that have
+  /// already been visited.
+  BoolValue (
+  BoolValue ,
+  llvm::DenseMap );
+
+  /// Builds and returns the logical formula defining the flow condition
+  /// identified by `Token`, sub values may be substituted based on entries in
+  /// `SubstitutionsCache`. Intermediate results are stored in
+  /// `SubstitutionsCache` to avoid reprocessing values that have already been
+  /// visited.
+  BoolValue (
+  AtomicBoolValue ,
+  llvm::DenseMap );
+
   std::unique_ptr S;
 
   // Storage for the state of a program.

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 9e4b03e36bb70..de48fd71b065b 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -202,6 +202,76 @@ void 
DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
   }
 }
 
+BoolValue ::substituteBoolValue(
+BoolValue ,
+llvm::DenseMap ) {
+  auto IT = SubstitutionsCache.find();
+  if (IT != SubstitutionsCache.end()) {
+return 

[clang] 12c7352 - [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.

2022-06-27 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-27T11:16:51+02:00
New Revision: 12c7352fa4885a61997cff26f9578bacc166df3b

URL: 
https://github.com/llvm/llvm-project/commit/12c7352fa4885a61997cff26f9578bacc166df3b
DIFF: 
https://github.com/llvm/llvm-project/commit/12c7352fa4885a61997cff26f9578bacc166df3b.diff

LOG: [clang][dataflow] Move logic for `createStorageLocation` from 
`DataflowEnvironment` to `DataflowAnalysisContext`.

`createStorageLocation` in `DataflowEnvironment` is now a trivial wrapper 
around the logic in `DataflowAnalysisContext`.
Additionally, `getObjectFields` and `getFieldsFromClassHierarchy` (required for 
the implementation of `createStorageLocation`) are also moved to 
`DataflowAnalysisContext`.

Reviewed By: gribozavr2, sgatev

Differential Revision: https://reviews.llvm.org/D128359

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 6011584f20064..58acd5639c436 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -44,6 +44,9 @@ namespace dataflow {
 const Expr (const Expr );
 const Stmt (const Stmt );
 
+/// Returns the set of all fields in the type.
+llvm::DenseSet getObjectFields(QualType Type);
+
 /// Owns objects that encompass the state of a program and stores context that
 /// is used during dataflow analysis.
 class DataflowAnalysisContext {
@@ -85,6 +88,19 @@ class DataflowAnalysisContext {
 return *cast(Vals.back().get());
   }
 
+  /// Returns a stable storage location appropriate for `Type`.
+  ///
+  /// Requirements:
+  ///
+  ///  `Type` must not be null.
+  StorageLocation (QualType Type);
+
+  /// Returns a stable storage location for `D`.
+  StorageLocation (const VarDecl );
+
+  /// Returns a stable storage location for `E`.
+  StorageLocation (const Expr );
+
   /// Assigns `Loc` as the storage location of `D`.
   ///
   /// Requirements:

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 475eeef537376..9e4b03e36bb70 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -22,6 +22,39 @@
 namespace clang {
 namespace dataflow {
 
+StorageLocation &
+DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
+  assert(!Type.isNull());
+  if (Type->isStructureOrClassType() || Type->isUnionType()) {
+// FIXME: Explore options to avoid eager initialization of fields as some 
of
+// them might not be needed for a particular analysis.
+llvm::DenseMap FieldLocs;
+for (const FieldDecl *Field : getObjectFields(Type))
+  FieldLocs.insert({Field, (Field->getType())});
+return takeOwnership(
+std::make_unique(Type, 
std::move(FieldLocs)));
+  }
+  return takeOwnership(std::make_unique(Type));
+}
+
+StorageLocation &
+DataflowAnalysisContext::getStableStorageLocation(const VarDecl ) {
+  if (auto *Loc = getStorageLocation(D))
+return *Loc;
+  auto  = getStableStorageLocation(D.getType());
+  setStorageLocation(D, Loc);
+  return Loc;
+}
+
+StorageLocation &
+DataflowAnalysisContext::getStableStorageLocation(const Expr ) {
+  if (auto *Loc = getStorageLocation(E))
+return *Loc;
+  auto  = getStableStorageLocation(E.getType());
+  setStorageLocation(E, Loc);
+  return Loc;
+}
+
 static std::pair
 makeCanonicalBoolValuePair(BoolValue , BoolValue ) {
   auto Res = std::make_pair(, );
@@ -190,3 +223,27 @@ const Stmt ::dataflow::ignoreCFGOmittedNodes(const 
Stmt ) {
 return ignoreCFGOmittedNodes(*E);
   return S;
 }
+
+// FIXME: Does not precisely handle non-virtual diamond inheritance. A single
+// field decl will be modeled for all instances of the inherited field.
+static void
+getFieldsFromClassHierarchy(QualType Type,
+llvm::DenseSet ) {
+  if (Type->isIncompleteType() || Type->isDependentType() ||
+  !Type->isRecordType())
+return;
+
+  for (const FieldDecl *Field : Type->getAsRecordDecl()->fields())
+Fields.insert(Field);
+  if (auto *CXXRecord = Type->getAsCXXRecordDecl())
+for (const CXXBaseSpecifier  : CXXRecord->bases())
+  getFieldsFromClassHierarchy(Base.getType(), Fields);
+}
+
+/// Gets the set of all fields in the type.
+llvm::DenseSet
+clang::dataflow::getObjectFields(QualType Type) {
+  llvm::DenseSet Fields;
+  getFieldsFromClassHierarchy(Type, Fields);
+  return Fields;
+}

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 

[clang] 0f65a3e - [clang][dataflow] Implement functionality to compare if two boolean values are equivalent.

2022-06-24 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-25T00:10:35+02:00
New Revision: 0f65a3e610051fc319372eea647fb50f60b2b21c

URL: 
https://github.com/llvm/llvm-project/commit/0f65a3e610051fc319372eea647fb50f60b2b21c
DIFF: 
https://github.com/llvm/llvm-project/commit/0f65a3e610051fc319372eea647fb50f60b2b21c.diff

LOG: [clang][dataflow] Implement functionality to compare if two boolean values 
are equivalent.

`equivalentBoolValues` compares equivalence between two booleans. The current 
implementation does not consider constraints imposed by flow conditions on the 
booleans and its subvalues.

Depends On D128520

Reviewed By: gribozavr2, xazax.hun

Differential Revision: https://reviews.llvm.org/D128521

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 8a1fc9745b21..6011584f2006 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -203,6 +203,11 @@ class DataflowAnalysisContext {
   /// identified by `Token` are always true.
   bool flowConditionIsTautology(AtomicBoolValue );
 
+  /// Returns true if `Val1` is equivalent to `Val2`.
+  /// Note: This function doesn't take into account constraints on `Val1` and
+  /// `Val2` imposed by the flow condition.
+  bool equivalentBoolValues(BoolValue , BoolValue );
+
 private:
   /// Adds all constraints of the flow condition identified by `Token` and all
   /// of its transitive dependencies to `Constraints`. `VisitedTokens` is used

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 57c8750a67e6..475eeef53737 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -137,6 +137,13 @@ bool 
DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue ) {
   return isUnsatisfiable(std::move(Constraints));
 }
 
+bool DataflowAnalysisContext::equivalentBoolValues(BoolValue ,
+   BoolValue ) {
+  llvm::DenseSet Constraints = {
+  (getOrCreateIff(Val1, Val2))};
+  return isUnsatisfiable(Constraints);
+}
+
 void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
 AtomicBoolValue , llvm::DenseSet ,
 llvm::DenseSet ) {

diff  --git 
a/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
index 1ff7cf1dce9e..1f0116cdbf2e 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
@@ -213,4 +213,67 @@ TEST_F(DataflowAnalysisContextTest, 
FlowConditionTautologies) {
   EXPECT_TRUE(Context.flowConditionIsTautology(FC5));
 }
 
+TEST_F(DataflowAnalysisContextTest, EquivBoolVals) {
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.getBoolLiteralValue(true);
+  auto  = Context.getBoolLiteralValue(false);
+
+  // X == X
+  EXPECT_TRUE(Context.equivalentBoolValues(X, X));
+  // X != Y
+  EXPECT_FALSE(Context.equivalentBoolValues(X, Y));
+
+  // !X != X
+  EXPECT_FALSE(Context.equivalentBoolValues(Context.getOrCreateNegation(X), 
X));
+  // !(!X) = X
+  EXPECT_TRUE(Context.equivalentBoolValues(
+  Context.getOrCreateNegation(Context.getOrCreateNegation(X)), X));
+
+  // (X || X) == X
+  EXPECT_TRUE(
+  Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, X), X));
+  // (X || Y) != X
+  EXPECT_FALSE(
+  Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, Y), X));
+  // (X || True) == True
+  EXPECT_TRUE(Context.equivalentBoolValues(
+  Context.getOrCreateDisjunction(X, True), True));
+  // (X || False) == X
+  EXPECT_TRUE(Context.equivalentBoolValues(
+  Context.getOrCreateDisjunction(X, False), X));
+
+  // (X && X) == X
+  EXPECT_TRUE(
+  Context.equivalentBoolValues(Context.getOrCreateConjunction(X, X), X));
+  // (X && Y) != X
+  EXPECT_FALSE(
+  Context.equivalentBoolValues(Context.getOrCreateConjunction(X, Y), X));
+  // (X && True) == X
+  EXPECT_TRUE(
+  Context.equivalentBoolValues(Context.getOrCreateConjunction(X, True), 
X));
+  // (X && False) == False
+  EXPECT_TRUE(Context.equivalentBoolValues(
+  Context.getOrCreateConjunction(X, False), False));
+
+  // (X || Y) == (Y || X)
+  EXPECT_TRUE(
+  

[clang] 42a7ddb - [clang][dataflow] Refactor function that queries the solver for satisfiability checking.

2022-06-24 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-25T00:05:43+02:00
New Revision: 42a7ddb428c999229491b0effbb1a4059149fba8

URL: 
https://github.com/llvm/llvm-project/commit/42a7ddb428c999229491b0effbb1a4059149fba8
DIFF: 
https://github.com/llvm/llvm-project/commit/42a7ddb428c999229491b0effbb1a4059149fba8.diff

LOG: [clang][dataflow] Refactor function that queries the solver for 
satisfiability checking.

Given a set of `Constraints`, `querySolver` adds common background information 
across queries (`TrueVal` is always true and `FalseVal` is always false) and 
passes the query to the solver.

`checkUnsatisfiable` is a simple wrapper around `querySolver` for checking that 
the solver returns an unsatisfiable result.

Depends On D128519

Reviewed By: gribozavr2, xazax.hun

Differential Revision: https://reviews.llvm.org/D128520

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 9f89b2ff5b831..8a1fc9745b215 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -212,6 +212,19 @@ class DataflowAnalysisContext {
   AtomicBoolValue , llvm::DenseSet ,
   llvm::DenseSet );
 
+  /// Returns the result of satisfiability checking on `Constraints`.
+  /// Possible return values are:
+  /// - `Satisfiable`: There exists a satisfying assignment for `Constraints`.
+  /// - `Unsatisfiable`: There is no satisfying assignment for `Constraints`.
+  /// - `TimedOut`: The solver gives up on finding a satisfying assignment.
+  Solver::Result querySolver(llvm::DenseSet Constraints);
+
+  /// Returns true if the solver is able to prove that there is no satisfying
+  /// assignment for `Constraints`
+  bool isUnsatisfiable(llvm::DenseSet Constraints) {
+return querySolver(std::move(Constraints)) == 
Solver::Result::Unsatisfiable;
+  }
+
   std::unique_ptr S;
 
   // Storage for the state of a program.

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 10e7df394f40f..57c8750a67e66 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -108,6 +108,13 @@ 
DataflowAnalysisContext::joinFlowConditions(AtomicBoolValue ,
   return Token;
 }
 
+Solver::Result
+DataflowAnalysisContext::querySolver(llvm::DenseSet Constraints) {
+  Constraints.insert((true));
+  Constraints.insert((getBoolLiteralValue(false)));
+  return S->solve(std::move(Constraints));
+}
+
 bool DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue ,
BoolValue ) {
   // Returns true if and only if truth assignment of the flow condition implies
@@ -115,28 +122,19 @@ bool 
DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue ,
   // reducing the problem to satisfiability checking. In other words, we 
attempt
   // to show that assuming `Val` is false makes the constraints induced by the
   // flow condition unsatisfiable.
-  llvm::DenseSet Constraints = {
-  ,
-  (true),
-  (getBoolLiteralValue(false)),
-  (Val),
-  };
+  llvm::DenseSet Constraints = {, 
(Val)};
   llvm::DenseSet VisitedTokens;
   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
-  return S->solve(std::move(Constraints)) == Solver::Result::Unsatisfiable;
+  return isUnsatisfiable(std::move(Constraints));
 }
 
 bool DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue ) 
{
   // Returns true if and only if we cannot prove that the flow condition can
   // ever be false.
-  llvm::DenseSet Constraints = {
-  (true),
-  (getBoolLiteralValue(false)),
-  (Token),
-  };
+  llvm::DenseSet Constraints = {(Token)};
   llvm::DenseSet VisitedTokens;
   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
-  return S->solve(std::move(Constraints)) == Solver::Result::Unsatisfiable;
+  return isUnsatisfiable(std::move(Constraints));
 }
 
 void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(



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


[clang] 00e9d53 - [clang][dataflow] Move logic for creating implication and iff expressions into `DataflowAnalysisContext` from `DataflowEnvironment`.

2022-06-24 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-24T23:16:44+02:00
New Revision: 00e9d53453abc8f2e3d69e9c7fba83dc65a74259

URL: 
https://github.com/llvm/llvm-project/commit/00e9d53453abc8f2e3d69e9c7fba83dc65a74259
DIFF: 
https://github.com/llvm/llvm-project/commit/00e9d53453abc8f2e3d69e9c7fba83dc65a74259.diff

LOG: [clang][dataflow] Move logic for creating implication and iff expressions 
into `DataflowAnalysisContext` from `DataflowEnvironment`.

To keep functionality of creating boolean expressions in a consistent location.

Depends On D128357

Reviewed By: gribozavr2, sgatev, xazax.hun

Differential Revision: https://reviews.llvm.org/D128519

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 48d0eedc49dde..9f89b2ff5b831 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -151,17 +151,29 @@ class DataflowAnalysisContext {
   /// `RHS`. Subsequent calls with the same arguments, regardless of their
   /// order, will return the same result. If the given boolean values represent
   /// the same value, the result will be the value itself.
-  BoolValue (BoolValue , BoolValue );
+  BoolValue (BoolValue , BoolValue );
 
   /// Returns a boolean value that represents the disjunction of `LHS` and
   /// `RHS`. Subsequent calls with the same arguments, regardless of their
   /// order, will return the same result. If the given boolean values represent
   /// the same value, the result will be the value itself.
-  BoolValue (BoolValue , BoolValue );
+  BoolValue (BoolValue , BoolValue );
 
   /// Returns a boolean value that represents the negation of `Val`. Subsequent
   /// calls with the same argument will return the same result.
-  BoolValue (BoolValue );
+  BoolValue (BoolValue );
+
+  /// Returns a boolean value that represents `LHS => RHS`. Subsequent calls
+  /// with the same arguments, will return the same result. If the given 
boolean
+  /// values represent the same value, the result will be a value that
+  /// represents the true boolean literal.
+  BoolValue (BoolValue , BoolValue );
+
+  /// Returns a boolean value that represents `LHS <=> RHS`. Subsequent calls
+  /// with the same arguments, regardless of their order, will return the same
+  /// result. If the given boolean values represent the same value, the result
+  /// will be a value that represents the true boolean literal.
+  BoolValue (BoolValue , BoolValue );
 
   /// Creates a fresh flow condition and returns a token that identifies it. 
The
   /// token can be used to perform various operations on the flow condition 
such

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 0a2c75f804c2a..ac49d22995c1d 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -268,7 +268,7 @@ class Environment {
   /// order, will return the same result. If the given boolean values represent
   /// the same value, the result will be the value itself.
   BoolValue (BoolValue , BoolValue ) const {
-return DACtx->getOrCreateConjunctionValue(LHS, RHS);
+return DACtx->getOrCreateConjunction(LHS, RHS);
   }
 
   /// Returns a boolean value that represents the disjunction of `LHS` and
@@ -276,21 +276,21 @@ class Environment {
   /// order, will return the same result. If the given boolean values represent
   /// the same value, the result will be the value itself.
   BoolValue (BoolValue , BoolValue ) const {
-return DACtx->getOrCreateDisjunctionValue(LHS, RHS);
+return DACtx->getOrCreateDisjunction(LHS, RHS);
   }
 
   /// Returns a boolean value that represents the negation of `Val`. Subsequent
   /// calls with the same argument will return the same result.
   BoolValue (BoolValue ) const {
-return DACtx->getOrCreateNegationValue(Val);
+return DACtx->getOrCreateNegation(Val);
   }
 
   /// Returns a boolean value represents `LHS` => `RHS`. Subsequent calls with
-  /// the same arguments, regardless of their order, will return the same
-  /// result. If the given boolean values represent the same value, the result
-  /// will be a value that represents the true boolean literal.
+  /// the same arguments, will return the same result. If the given boolean
+  /// values 

[clang] fb88ea6 - [clang][dataflow] Store flow condition constraints in a single `FlowConditionConstraints` map.

2022-06-24 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-24T21:52:16+02:00
New Revision: fb88ea62602c90f8f7c80560fd6a14f1c8c6d520

URL: 
https://github.com/llvm/llvm-project/commit/fb88ea62602c90f8f7c80560fd6a14f1c8c6d520
DIFF: 
https://github.com/llvm/llvm-project/commit/fb88ea62602c90f8f7c80560fd6a14f1c8c6d520.diff

LOG: [clang][dataflow] Store flow condition constraints in a single 
`FlowConditionConstraints` map.

A flow condition is represented with an atomic boolean token, and it is bound 
to a set of constraints: `(FC <=> C1 ^ C2 ^ ...)`. \
This was internally represented as `(FC v !C1 v !C2 v ...) ^ (C1 v !FC) ^ (C2 v 
!FC) ^ ...` and tracked by 2 maps:
- `FlowConditionFirstConjunct` stores the first conjunct `(FC v !C1 v !C2 v 
...)`
- `FlowConditionRemainingConjuncts` stores the remaining conjuncts `(C1 v !FC) 
^ (C2 v !FC) ^ ...`

This patch simplifies the tracking of the constraints by using a single 
`FlowConditionConstraints` map which stores `(C1 ^ C2 ^ ...)`, eliminating the 
use of two maps.

Reviewed By: gribozavr2, sgatev, xazax.hun

Differential Revision: https://reviews.llvm.org/D128357

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index e2820fcb55655..48d0eedc49dde 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -198,7 +198,7 @@ class DataflowAnalysisContext {
   /// calls.
   void addTransitiveFlowConditionConstraints(
   AtomicBoolValue , llvm::DenseSet ,
-  llvm::DenseSet ) const;
+  llvm::DenseSet );
 
   std::unique_ptr S;
 
@@ -232,21 +232,16 @@ class DataflowAnalysisContext {
   // defines the flow condition. Conceptually, each binding corresponds to an
   // "iff" of the form `FC <=> (C1 ^ C2 ^ ...)` where `FC` is a flow condition
   // token (an atomic boolean) and `Ci`s are the set of constraints in the flow
-  // flow condition clause. Internally, we do not record the formula directly 
as
-  // an "iff". Instead, a flow condition clause is encoded as conjuncts of the
-  // form `(FC v !C1 v !C2 v ...) ^ (C1 v !FC) ^ (C2 v !FC) ^ ...`. The first
-  // conjuct is stored in the `FlowConditionFirstConjuncts` map and the set of
-  // remaining conjuncts are stored in the `FlowConditionRemainingConjuncts`
-  // map, both keyed by the token of the flow condition.
+  // flow condition clause. The set of constraints (C1 ^ C2 ^ ...) are stored 
in
+  // the `FlowConditionConstraints` map, keyed by the token of the flow
+  // condition.
   //
   // Flow conditions depend on other flow conditions if they are created using
   // `forkFlowCondition` or `joinFlowConditions`. The graph of flow condition
   // dependencies is stored in the `FlowConditionDeps` map.
   llvm::DenseMap>
   FlowConditionDeps;
-  llvm::DenseMap FlowConditionFirstConjuncts;
-  llvm::DenseMap>
-  FlowConditionRemainingConjuncts;
+  llvm::DenseMap FlowConditionConstraints;
 };
 
 } // namespace dataflow

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 81e37e6e6905a..ffd552b1fdc72 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -66,19 +66,16 @@ BoolValue 
::getOrCreateNegationValue(BoolValue ) {
 }
 
 AtomicBoolValue ::makeFlowConditionToken() {
-  AtomicBoolValue  = createAtomicBoolValue();
-  FlowConditionRemainingConjuncts[] = {};
-  FlowConditionFirstConjuncts[] = 
-  return Token;
+  return createAtomicBoolValue();
 }
 
 void DataflowAnalysisContext::addFlowConditionConstraint(
 AtomicBoolValue , BoolValue ) {
-  FlowConditionRemainingConjuncts[].insert((
-  Constraint, getOrCreateNegationValue(Token)));
-  FlowConditionFirstConjuncts[] =
-  (*FlowConditionFirstConjuncts[],
-   getOrCreateNegationValue(Constraint));
+  auto Res = FlowConditionConstraints.try_emplace(, );
+  if (!Res.second) {
+Res.first->second =
+(*Res.first->second, Constraint);
+  }
 }
 
 AtomicBoolValue &
@@ -133,24 +130,30 @@ bool 
DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue ) {
 
 void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
 AtomicBoolValue , llvm::DenseSet ,
-llvm::DenseSet ) const {
+llvm::DenseSet ) {
   auto Res = VisitedTokens.insert();
   if (!Res.second)
 return;
 
-  auto FirstConjunctIT = FlowConditionFirstConjuncts.find();
-  if (FirstConjunctIT != FlowConditionFirstConjuncts.end())
-Constraints.insert(FirstConjunctIT->second);
-  auto 

[clang] 37b881a - clang: Tweak behaviour of warn_empty_while_body and warn_empty_if_body

2022-06-23 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-06-24T02:40:25+02:00
New Revision: 37b881aa0bca09b7cc80575cc4b97453aa724186

URL: 
https://github.com/llvm/llvm-project/commit/37b881aa0bca09b7cc80575cc4b97453aa724186
DIFF: 
https://github.com/llvm/llvm-project/commit/37b881aa0bca09b7cc80575cc4b97453aa724186.diff

LOG: clang: Tweak behaviour of warn_empty_while_body and warn_empty_if_body

Use the if/while statement right paren location instead of the end of the
condition expression to determine if the semicolon is on its own line, for the
purpose of not warning about code like this:

while (foo())
  ;

Using the condition location meant that we would also not report a warning on
code like this:

while (MACRO(a,
 b));
  body();

The right paren loc wasn't stored in the AST or passed into Sema::ActOnIfStmt
when this logic was first written.

Reviewed By: rnk, gribozavr2

Differential Revision: https://reviews.llvm.org/D128406

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/CXX/stmt.stmt/stmt.select/p3.cpp
clang/test/SemaCXX/warn-empty-body.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 58f803ed00243..4357e45c6a14a 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16673,7 +16673,7 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
 Body = FS->getBody();
 DiagID = diag::warn_empty_for_body;
   } else if (const WhileStmt *WS = dyn_cast(S)) {
-StmtLoc = WS->getCond()->getSourceRange().getEnd();
+StmtLoc = WS->getRParenLoc();
 Body = WS->getBody();
 DiagID = diag::warn_empty_while_body;
   } else

diff  --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index ae3ea4db233e5..82831a448869d 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -888,8 +888,7 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc,
 CommaVisitor(*this).Visit(CondExpr);
 
   if (!ConstevalOrNegatedConsteval && !elseStmt)
-DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt,
-  diag::warn_empty_if_body);
+DiagnoseEmptyStmtBody(RParenLoc, thenStmt, diag::warn_empty_if_body);
 
   if (ConstevalOrNegatedConsteval ||
   StatementKind == IfStatementKind::Constexpr) {

diff  --git a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp 
b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp
index 4804cc559d007..2d45d82d43754 100644
--- a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -63,8 +63,6 @@ void whileInitStatement() {
   // expected-note@-1 {{to match this '('}}
   // expected-error@-2 {{expected ';' after expression}}
   // expected-error@-3 {{expected expression}}
-  // expected-warning@-4 {{while loop has empty body}}
-  // expected-note@-5 {{put the semicolon on a separate line to silence this 
warning}}
 }
 
 // TODO: This is needed because clang can't seem to diagnose invalid syntax 
after the

diff  --git a/clang/test/SemaCXX/warn-empty-body.cpp 
b/clang/test/SemaCXX/warn-empty-body.cpp
index a248c4251d525..08cfb57e90e07 100644
--- a/clang/test/SemaCXX/warn-empty-body.cpp
+++ b/clang/test/SemaCXX/warn-empty-body.cpp
@@ -6,6 +6,8 @@ int c();
 
 #define MACRO_A 0
 
+#define AND(x, y) ((x) && (y))
+
 void test1(int x, int y) {
   while(true) {
 if (x); // expected-warning {{if statement has empty body}} 
expected-note{{put the semicolon on a separate line to silence this warning}}
@@ -15,6 +17,15 @@ void test1(int x, int y) {
 if (x == MACRO_A); // expected-warning {{if statement has empty body}} 
expected-note{{put the semicolon on a separate line to silence this warning}}
 if (MACRO_A == x); // expected-warning {{if statement has empty body}} 
expected-note{{put the semicolon on a separate line to silence this warning}}
 
+// Check that we handle the case where the condition comes from a macro
+// expansion over multiple lines.
+if (AND(b(),
+c())); // expected-warning {{if statement has empty body}} 
expected-note{{put the semicolon on a separate line to silence this warning}}
+
+while (AND(b(),
+   c())); // expected-warning{{while loop has empty body}} 
expected-note{{put the semicolon on a separate line to silence this warning}}
+  a(0);
+
 int i;
 // PR11329
 for (i = 0; i < x; i++); { // expected-warning{{for loop has empty body}} 
expected-note{{put the semicolon on a separate line to silence this warning}}



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


[clang] 97d69cd - [clang][dataflow] Rename `getPointeeLoc` to `getReferentLoc` for ReferenceValue.

2022-06-14 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-15T00:53:30+02:00
New Revision: 97d69cdaf324ec520b3f7685ef05f8e207a7bd3b

URL: 
https://github.com/llvm/llvm-project/commit/97d69cdaf324ec520b3f7685ef05f8e207a7bd3b
DIFF: 
https://github.com/llvm/llvm-project/commit/97d69cdaf324ec520b3f7685ef05f8e207a7bd3b.diff

LOG: [clang][dataflow] Rename `getPointeeLoc` to `getReferentLoc` for 
ReferenceValue.

We distinguish between the referent location for `ReferenceValue` and pointee 
location for `PointerValue`. The former must be non-empty but the latter may be 
empty in the case of a `nullptr`

Reviewed By: gribozavr2, sgatev

Differential Revision: https://reviews.llvm.org/D127745

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/Value.h
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/Value.h 
b/clang/include/clang/Analysis/FlowSensitive/Value.h
index 3ac4b8c60996b..9c93456346b23 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Value.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Value.h
@@ -170,17 +170,17 @@ class IntegerValue : public Value {
 /// in C.
 class ReferenceValue final : public Value {
 public:
-  explicit ReferenceValue(StorageLocation )
-  : Value(Kind::Reference), PointeeLoc(PointeeLoc) {}
+  explicit ReferenceValue(StorageLocation )
+  : Value(Kind::Reference), ReferentLoc(ReferentLoc) {}
 
   static bool classof(const Value *Val) {
 return Val->getKind() == Kind::Reference;
   }
 
-  StorageLocation () const { return PointeeLoc; }
+  StorageLocation () const { return ReferentLoc; }
 
 private:
-  StorageLocation 
+  StorageLocation 
 };
 
 /// Models a symbolic pointer. Specifically, any value of type `T*`.

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 033ef6afbeb2f..370b420b80755 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -53,7 +53,7 @@ llvm::DenseMap intersectDenseMaps(const 
llvm::DenseMap ,
 static bool areEquivalentIndirectionValues(Value *Val1, Value *Val2) {
   if (auto *IndVal1 = dyn_cast(Val1)) {
 auto *IndVal2 = cast(Val2);
-return >getPointeeLoc() == >getPointeeLoc();
+return >getReferentLoc() == >getReferentLoc();
   }
   if (auto *IndVal1 = dyn_cast(Val1)) {
 auto *IndVal2 = cast(Val2);
@@ -522,7 +522,7 @@ StorageLocation ::skip(StorageLocation , 
SkipPast SP) const {
 // References cannot be chained so we only need to skip past one level of
 // indirection.
 if (auto *Val = dyn_cast_or_null(getValue(Loc)))
-  return Val->getPointeeLoc();
+  return Val->getReferentLoc();
 return Loc;
   case SkipPast::ReferenceThenPointer:
 StorageLocation  = skip(Loc, SkipPast::Reference);

diff  --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
index f837fe31c6cd8..23a9d964b5b15 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -236,7 +236,7 @@ StorageLocation 
*maybeInitializeOptionalValueMember(QualType Q,
   // `Value` representing the optional (here, `OptionalVal`).
   if (auto *ValueProp = OptionalVal.getProperty("value")) {
 auto *ValueRef = clang::cast(ValueProp);
-auto  = ValueRef->getPointeeLoc();
+auto  = ValueRef->getReferentLoc();
 if (Env.getValue(ValueLoc) == nullptr) {
   // The property was previously set, but the value has been lost. This can
   // happen, for example, because of an environment merge (where the two

diff  --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 5780968d81591..e3c97367b17ca 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -293,29 +293,29 @@ TEST_F(TransferTest, ReferenceVarDecl) {
   // [[p]]
 }
   )";
-  runDataflow(Code,
-  [](llvm::ArrayRef<
- std::pair>>
- Results,
- ASTContext ) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment  = Results[0].second.Env;
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
 
-const ValueDecl *FooDecl = 

[clang-tools-extra] 11f75e0 - [clang-tidy][docs] Remove an unintentional paragraph break

2022-06-11 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-06-11T21:03:43+02:00
New Revision: 11f75e0a2dfa1455eee097dfa72686d8a4dc7802

URL: 
https://github.com/llvm/llvm-project/commit/11f75e0a2dfa1455eee097dfa72686d8a4dc7802
DIFF: 
https://github.com/llvm/llvm-project/commit/11f75e0a2dfa1455eee097dfa72686d8a4dc7802.diff

LOG: [clang-tidy][docs] Remove an unintentional paragraph break

Added: 


Modified: 

clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst

Removed: 




diff  --git 
a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
index 5d8b76aec771..3ed6372840a8 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
@@ -4,8 +4,8 @@ bugprone-unchecked-optional-access
 ==
 
 *Note*: This check uses a flow-sensitive static analysis to produce its
- results. Therefore, it may be more resource intensive (RAM, CPU) than the
- average clang-tidy check.
+results. Therefore, it may be more resource intensive (RAM, CPU) than the
+average clang-tidy check.
 
 This check identifies unsafe accesses to values contained in
 ``std::optional``, ``absl::optional``, or ``base::Optional``



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


[clang-tools-extra] 65299c9 - [clang-tidy][docs] Use std::optional instead of absl::optional in examples

2022-06-11 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-06-11T21:03:43+02:00
New Revision: 65299c9c652f3ce4958011ffe28119d0eff0f38d

URL: 
https://github.com/llvm/llvm-project/commit/65299c9c652f3ce4958011ffe28119d0eff0f38d
DIFF: 
https://github.com/llvm/llvm-project/commit/65299c9c652f3ce4958011ffe28119d0eff0f38d.diff

LOG: [clang-tidy][docs] Use std::optional instead of absl::optional in examples

The standard type is vastly more popular than the Abseil polyfill, so it
makes more sense to use it in documentation, even though the checker
actually understands both (and that fact is documented already).

Added: 


Modified: 

clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst

Removed: 




diff  --git 
a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
index 9c53c8a6d175f..5d8b76aec771d 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst
@@ -42,7 +42,7 @@ existence check:
 
 .. code-block:: c++
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  use(*opt); // unsafe: it is unclear whether `opt` has a value.
}
 
@@ -54,7 +54,7 @@ branches of the code. For example:
 
 .. code-block:: c++
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  if (opt.has_value()) {
  } else {
use(opt.value()); // unsafe: it is clear that `opt` does *not* have a 
value.
@@ -99,11 +99,11 @@ optional has a value. For example:
 
 .. code-block:: c++
 
-   void g(absl::optional opt) {
+   void g(std::optional opt) {
  use(*opt); // unsafe: it is unclear whether `opt` has a value.
}
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  if (opt.has_value()) {
g(opt);
  }
@@ -121,7 +121,7 @@ example:
 
 .. code-block:: c++
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  if (opt.has_value()) {
use(*opt);
  }
@@ -137,9 +137,9 @@ have a value. For example:
 
 .. code-block:: c++
 
-   void f(absl::optional opt1) {
+   void f(std::optional opt1) {
  if (opt1.has_value()) {
-   absl::optional opt2 = opt1;
+   std::optional opt2 = opt1;
use(*opt2);
  }
}
@@ -154,7 +154,7 @@ a value. For example:
 
 .. code-block:: c++
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  DCHECK(opt.has_value());
  use(*opt);
}
@@ -168,7 +168,7 @@ paths that lead to an access. For example:
 
 .. code-block:: c++
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  bool safe = false;
  if (opt.has_value() && SomeOtherCondition()) {
safe = true;
@@ -223,7 +223,7 @@ check the optional again in the local scope of the callee. 
For example:
  use(val);
}
 
-   void f(absl::optional opt) {
+   void f(std::optional opt) {
  if (opt.has_value()) {
g(*opt);
  }
@@ -234,7 +234,7 @@ and
 .. code-block:: c++
 
struct S {
- absl::optional opt;
+ std::optional opt;
  int x;
};
 
@@ -260,7 +260,7 @@ The check is aware of aliases of optional types that are 
created via
 
 .. code-block:: c++
 
-   using OptionalInt = absl::optional;
+   using OptionalInt = std::optional;
 
void f(OptionalInt opt) {
  use(opt.value()); // unsafe: it is unclear whether `opt` has a value.



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


[clang] a1b2b7d - [clang][dataflow] Remove IndirectionValue class, moving PointeeLoc field into PointerValue and ReferenceValue

2022-06-08 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-09T01:29:16+02:00
New Revision: a1b2b7d9790b8a150d798fcc672387607986dbe0

URL: 
https://github.com/llvm/llvm-project/commit/a1b2b7d9790b8a150d798fcc672387607986dbe0
DIFF: 
https://github.com/llvm/llvm-project/commit/a1b2b7d9790b8a150d798fcc672387607986dbe0.diff

LOG: [clang][dataflow] Remove IndirectionValue class, moving PointeeLoc field 
into PointerValue and ReferenceValue

This patch precedes a future patch to make PointeeLoc for PointerValue possibly 
empty (for nullptr), by using a pointer instead of a reference type.
ReferenceValue should maintain a non-empty PointeeLoc reference.

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D127312

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/Value.h
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/Value.h 
b/clang/include/clang/Analysis/FlowSensitive/Value.h
index 1aedd8a300dd5..3ac4b8c60996b 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Value.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Value.h
@@ -166,15 +166,15 @@ class IntegerValue : public Value {
   }
 };
 
-/// Base class for values that refer to storage locations.
-class IndirectionValue : public Value {
+/// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
+/// in C.
+class ReferenceValue final : public Value {
 public:
-  /// Constructs a value that refers to `PointeeLoc`.
-  explicit IndirectionValue(Kind ValueKind, StorageLocation )
-  : Value(ValueKind), PointeeLoc(PointeeLoc) {}
+  explicit ReferenceValue(StorageLocation )
+  : Value(Kind::Reference), PointeeLoc(PointeeLoc) {}
 
   static bool classof(const Value *Val) {
-return Val->getKind() == Kind::Reference || Val->getKind() == 
Kind::Pointer;
+return Val->getKind() == Kind::Reference;
   }
 
   StorageLocation () const { return PointeeLoc; }
@@ -183,27 +183,20 @@ class IndirectionValue : public Value {
   StorageLocation 
 };
 
-/// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
-/// in C.
-class ReferenceValue final : public IndirectionValue {
-public:
-  explicit ReferenceValue(StorageLocation )
-  : IndirectionValue(Kind::Reference, PointeeLoc) {}
-
-  static bool classof(const Value *Val) {
-return Val->getKind() == Kind::Reference;
-  }
-};
-
 /// Models a symbolic pointer. Specifically, any value of type `T*`.
-class PointerValue final : public IndirectionValue {
+class PointerValue final : public Value {
 public:
   explicit PointerValue(StorageLocation )
-  : IndirectionValue(Kind::Pointer, PointeeLoc) {}
+  : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
 
   static bool classof(const Value *Val) {
 return Val->getKind() == Kind::Pointer;
   }
+
+  StorageLocation () const { return PointeeLoc; }
+
+private:
+  StorageLocation 
 };
 
 /// Models a value of `struct` or `class` type, with a flat map of fields to

diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 13fef0d4286cf..033ef6afbeb2f 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -50,22 +50,25 @@ llvm::DenseMap intersectDenseMaps(const 
llvm::DenseMap ,
   return Result;
 }
 
+static bool areEquivalentIndirectionValues(Value *Val1, Value *Val2) {
+  if (auto *IndVal1 = dyn_cast(Val1)) {
+auto *IndVal2 = cast(Val2);
+return >getPointeeLoc() == >getPointeeLoc();
+  }
+  if (auto *IndVal1 = dyn_cast(Val1)) {
+auto *IndVal2 = cast(Val2);
+return >getPointeeLoc() == >getPointeeLoc();
+  }
+  return false;
+}
+
 /// Returns true if and only if `Val1` is equivalent to `Val2`.
 static bool equivalentValues(QualType Type, Value *Val1,
  const Environment , Value *Val2,
  const Environment ,
  Environment::ValueModel ) {
-  if (Val1 == Val2)
-return true;
-
-  if (auto *IndVal1 = dyn_cast(Val1)) {
-auto *IndVal2 = cast(Val2);
-assert(IndVal1->getKind() == IndVal2->getKind());
-if (>getPointeeLoc() == >getPointeeLoc())
-  return true;
-  }
-
-  return Model.compareEquivalent(Type, *Val1, Env1, *Val2, Env2);
+  return Val1 == Val2 || areEquivalentIndirectionValues(Val1, Val2) ||
+ Model.compareEquivalent(Type, *Val1, Env1, *Val2, Env2);
 }
 
 /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`,
@@ -89,12 +92,8 @@ static Value *mergeDistinctValues(QualType Type, Value *Val1,
   }
 
   // FIXME: add unit tests that cover this statement.
-  if (auto *IndVal1 = dyn_cast(Val1)) {
-auto *IndVal2 = cast(Val2);
-assert(IndVal1->getKind() == 

[clang] 49ed5bf - [clang][dataflow] Enable use of synthetic properties on all Value instances.

2022-06-08 Thread Dmitri Gribenko via cfe-commits

Author: Wei Yi Tee
Date: 2022-06-08T20:20:26+02:00
New Revision: 49ed5bf51958aaeb209804da794c85d06207c3ed

URL: 
https://github.com/llvm/llvm-project/commit/49ed5bf51958aaeb209804da794c85d06207c3ed
DIFF: 
https://github.com/llvm/llvm-project/commit/49ed5bf51958aaeb209804da794c85d06207c3ed.diff

LOG: [clang][dataflow] Enable use of synthetic properties on all Value 
instances.

This patch moves the implementation of synthetic properties from the 
StructValue class into the Value base class so that it can be used across all 
Value instances.

Reviewed By: gribozavr2, ymandel, sgatev, xazax.hun

Differential Revision: https://reviews.llvm.org/D127196

Added: 


Modified: 
clang/include/clang/Analysis/FlowSensitive/Value.h
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/Value.h 
b/clang/include/clang/Analysis/FlowSensitive/Value.h
index 859cf7ff21b5b..1aedd8a300dd5 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Value.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Value.h
@@ -26,6 +26,9 @@ namespace clang {
 namespace dataflow {
 
 /// Base class for all values computed by abstract interpretation.
+///
+/// Don't use `Value` instances by value. All `Value` instances are allocated
+/// and owned by `DataflowAnalysisContext`.
 class Value {
 public:
   enum class Kind {
@@ -48,8 +51,22 @@ class Value {
 
   Kind getKind() const { return ValKind; }
 
+  /// Returns the value of the synthetic property with the given `Name` or null
+  /// if the property isn't assigned a value.
+  Value *getProperty(llvm::StringRef Name) const {
+auto It = Properties.find(Name);
+return It == Properties.end() ? nullptr : It->second;
+  }
+
+  /// Assigns `Val` as the value of the synthetic property with the given
+  /// `Name`.
+  void setProperty(llvm::StringRef Name, Value ) {
+Properties.insert_or_assign(Name, );
+  }
+
 private:
   Kind ValKind;
+  llvm::StringMap Properties;
 };
 
 /// Models a boolean.
@@ -215,22 +232,8 @@ class StructValue final : public Value {
   /// Assigns `Val` as the child value for `D`.
   void setChild(const ValueDecl , Value ) { Children[] =  }
 
-  /// Returns the value of the synthetic property with the given `Name` or null
-  /// if the property isn't assigned a value.
-  Value *getProperty(llvm::StringRef Name) const {
-auto It = Properties.find(Name);
-return It == Properties.end() ? nullptr : It->second;
-  }
-
-  /// Assigns `Val` as the value of the synthetic property with the given
-  /// `Name`.
-  void setProperty(llvm::StringRef Name, Value ) {
-Properties.insert_or_assign(Name, );
-  }
-
 private:
   llvm::DenseMap Children;
-  llvm::StringMap Properties;
 };
 
 } // namespace dataflow

diff  --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
index 02cf2c75579ff..cf93a07f832df 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -178,9 +178,9 @@ StructValue (Environment , 
BoolValue ) {
 }
 
 /// Returns the symbolic value that represents the "has_value" property of the
-/// optional value `Val`. Returns null if `Val` is null.
-BoolValue *getHasValue(Value *Val) {
-  if (auto *OptionalVal = cast_or_null(Val)) {
+/// optional value `OptionalVal`. Returns null if `OptionalVal` is null.
+BoolValue *getHasValue(Value *OptionalVal) {
+  if (OptionalVal) {
 return cast(OptionalVal->getProperty("has_value"));
   }
   return nullptr;
@@ -221,8 +221,8 @@ int countOptionalWrappers(const ASTContext , 
QualType Type) {
 void initializeOptionalReference(const Expr *OptionalExpr,
  const MatchFinder::MatchResult &,
  LatticeTransferState ) {
-  if (auto *OptionalVal = cast_or_null(
-  State.Env.getValue(*OptionalExpr, SkipPast::Reference))) {
+  if (auto *OptionalVal =
+  State.Env.getValue(*OptionalExpr, SkipPast::Reference)) {
 if (OptionalVal->getProperty("has_value") == nullptr) {
   OptionalVal->setProperty("has_value", State.Env.makeAtomicBoolValue());
 }
@@ -231,8 +231,8 @@ void initializeOptionalReference(const Expr *OptionalExpr,
 
 void transferUnwrapCall(const Expr *UnwrapExpr, const Expr *ObjectExpr,
 LatticeTransferState ) {
-  if (auto *OptionalVal = cast_or_null(
-  State.Env.getValue(*ObjectExpr, SkipPast::ReferenceThenPointer))) {
+  if (auto *OptionalVal =
+  State.Env.getValue(*ObjectExpr, SkipPast::ReferenceThenPointer)) {
 auto *HasValueVal = getHasValue(OptionalVal);
 assert(HasValueVal != nullptr);
 

diff  --git 

[clang-tools-extra] 9c6a2f2 - Fix an unused variable warning in no-asserts build mode

2022-05-17 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-05-17T15:27:44+02:00
New Revision: 9c6a2f29660b886044a267bb4de662cd801079bc

URL: 
https://github.com/llvm/llvm-project/commit/9c6a2f29660b886044a267bb4de662cd801079bc
DIFF: 
https://github.com/llvm/llvm-project/commit/9c6a2f29660b886044a267bb4de662cd801079bc.diff

LOG: Fix an unused variable warning in no-asserts build mode

Added: 


Modified: 
clang-tools-extra/pseudo/lib/GLR.cpp

Removed: 




diff  --git a/clang-tools-extra/pseudo/lib/GLR.cpp 
b/clang-tools-extra/pseudo/lib/GLR.cpp
index cf0a370820e1..10fa0d0568c0 100644
--- a/clang-tools-extra/pseudo/lib/GLR.cpp
+++ b/clang-tools-extra/pseudo/lib/GLR.cpp
@@ -40,6 +40,7 @@ const ForestNode (const TokenStream , const 
ParseParams ,
SymbolID StartSymbol) {
   llvm::ArrayRef Terminals = Params.Forest.createTerminals(Tokens);
   auto  = Params.G;
+  (void)G;
   auto  = Params.GSStack;
 
   // Lists of active shift, reduce, accept actions.



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


[clang] f2b31f0 - re-roll-forward "[clang] Mark `trivial_abi` types as "trivially relocatable"".""

2022-04-28 Thread Dmitri Gribenko via cfe-commits

Author: Devin Jeanpierre
Date: 2022-04-28T14:53:59+02:00
New Revision: f2b31f06b79a6cfb7eb3146dfc1d514da52142e9

URL: 
https://github.com/llvm/llvm-project/commit/f2b31f06b79a6cfb7eb3146dfc1d514da52142e9
DIFF: 
https://github.com/llvm/llvm-project/commit/f2b31f06b79a6cfb7eb3146dfc1d514da52142e9.diff

LOG: re-roll-forward "[clang] Mark `trivial_abi` types as "trivially 
relocatable"".""

This reverts commit b0bc93da926a943cdc2d8b04f8dcbe23a774520c.

Changes: `s/_WIN32/_WIN64/g` in clang/test/SemaCXX/attr-trivial-abi.cpp.

The calling convention is specific to 64-bit windows. It's even in the name: 
`CCK_MicrosoftWin64`.

After this, the test passes with both `-triple i686-pc-win32` and `-triple 
x86_64-pc-win32`. Phew!

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D123059

Added: 


Modified: 
clang/docs/LanguageExtensions.rst
clang/include/clang/AST/Type.h
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/TokenKinds.def
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/SemaCXX/attr-trivial-abi.cpp
clang/test/SemaCXX/type-traits.cpp
clang/test/SemaObjCXX/arc-type-traits.mm
clang/test/SemaObjCXX/objc-weak-type-traits.mm

Removed: 




diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 0391102fb222c..fbc881a724bb2 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1434,6 +1434,11 @@ The following type trait primitives are supported by 
Clang. Those traits marked
 * ``__is_trivially_constructible`` (C++, GNU, Microsoft)
 * ``__is_trivially_copyable`` (C++, GNU, Microsoft)
 * ``__is_trivially_destructible`` (C++, MSVC 2013)
+* ``__is_trivially_relocatable`` (Clang): Returns true if moving an object
+  of the given type, and then destroying the source object, is known to be
+  functionally equivalent to copying the underlying bytes and then dropping the
+  source object on the floor. This is true of trivial types and types which
+  were made trivially relocatable via the ``clang::trivial_abi`` attribute.
 * ``__is_union`` (C++, GNU, Microsoft, Embarcadero)
 * ``__is_unsigned`` (C++, Embarcadero):
   Returns false for enumeration types. Note, before Clang 13, returned true for

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 1a8549bedb4f9..45b75fe7960c3 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -830,6 +830,8 @@ class QualType {
   /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
   bool isTriviallyCopyableType(const ASTContext ) const;
 
+  /// Return true if this is a trivially relocatable type.
+  bool isTriviallyRelocatableType(const ASTContext ) const;
 
   /// Returns true if it is a class and it might be dynamic.
   bool mayBeDynamicClass() const;

diff  --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 00d6b035ff3cf..02b6031fd5aa5 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -,6 +,9 @@ If a type is trivial for the purposes of calls, has a 
non-trivial destructor,
 and is passed as an argument by value, the convention is that the callee will
 destroy the object before returning.
 
+If a type is trivial for the purpose of calls, it is assumed to be trivially
+relocatable for the purpose of ``__is_trivially_relocatable``.
+
 Attribute ``trivial_abi`` has no effect in the following cases:
 
 - The class directly declares a virtual base or virtual methods.

diff  --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 5092780d8f60f..093389615c263 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -511,6 +511,7 @@ TYPE_TRAIT_1(__has_unique_object_representations,
 KEYWORD(__underlying_type   , KEYCXX)
 
 // Clang-only C++ Type Traits
+TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
 TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
 
 // Embarcadero Expression Traits

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index bb9900ea6eea4..92450e8f5f2f5 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2505,6 +2505,25 @@ bool QualType::isTriviallyCopyableType(const ASTContext 
) const {
   return false;
 }
 
+bool QualType::isTriviallyRelocatableType(const ASTContext ) const {
+  QualType BaseElementType = Context.getBaseElementType(*this);
+
+  if (BaseElementType->isIncompleteType()) {
+return false;
+  } else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
+return RD->canPassInRegisters();
+  } else {
+switch (isNonTrivialToPrimitiveDestructiveMove()) {
+case PCK_Trivial:
+  return !isDestructedType();
+case PCK_ARCStrong:

[clang] 56d46b3 - [clang] roll-forward "[clang] Mark `trivial_abi` types as "trivially relocatable"".

2022-02-04 Thread Dmitri Gribenko via cfe-commits

Author: Devin Jeanpierre
Date: 2022-02-04T20:17:34+01:00
New Revision: 56d46b36fc231a0beb518602503035bba92043e0

URL: 
https://github.com/llvm/llvm-project/commit/56d46b36fc231a0beb518602503035bba92043e0
DIFF: 
https://github.com/llvm/llvm-project/commit/56d46b36fc231a0beb518602503035bba92043e0.diff

LOG: [clang] roll-forward "[clang] Mark `trivial_abi` types as "trivially 
relocatable"".

This reverts commit 852afed5e0200b70047c28ccf4424a17089d17b0.

Changes since D114732:

On PS4, we reverse the expectation that classes whose constructor is deleted 
are not trivially relocatable. Because, at the moment, only classes which are 
passed in registers are trivially relocatable, and PS4 allows passing in 
registers if the copy constructor is deleted, the original assertions were 
broken on PS4.

(This is kinda similar to DR1734.)

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D119017

Added: 


Modified: 
clang/docs/LanguageExtensions.rst
clang/include/clang/AST/Type.h
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/TokenKinds.def
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/SemaCXX/attr-trivial-abi.cpp
clang/test/SemaCXX/type-traits.cpp
clang/test/SemaObjCXX/arc-type-traits.mm
clang/test/SemaObjCXX/objc-weak-type-traits.mm

Removed: 




diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index f848fb01d8c5e..e74539d650ce0 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1365,6 +1365,11 @@ The following type trait primitives are supported by 
Clang. Those traits marked
 * ``__is_trivially_constructible`` (C++, GNU, Microsoft)
 * ``__is_trivially_copyable`` (C++, GNU, Microsoft)
 * ``__is_trivially_destructible`` (C++, MSVC 2013)
+* ``__is_trivially_relocatable`` (Clang): Returns true if moving an object
+  of the given type, and then destroying the source object, is known to be
+  functionally equivalent to copying the underlying bytes and then dropping the
+  source object on the floor. This is true of trivial types and types which
+  were made trivially relocatable via the ``clang::trivial_abi`` attribute.
 * ``__is_union`` (C++, GNU, Microsoft, Embarcadero)
 * ``__is_unsigned`` (C++, Embarcadero):
   Returns false for enumeration types. Note, before Clang 13, returned true for

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index a69c0ae67d0a0..3c71cbbb9c8f3 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -829,6 +829,8 @@ class QualType {
   /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
   bool isTriviallyCopyableType(const ASTContext ) const;
 
+  /// Return true if this is a trivially relocatable type.
+  bool isTriviallyRelocatableType(const ASTContext ) const;
 
   /// Returns true if it is a class and it might be dynamic.
   bool mayBeDynamicClass() const;

diff  --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index efd2af1ab1df3..e12a0b259cc2e 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -3295,6 +3295,9 @@ If a type is trivial for the purposes of calls, has a 
non-trivial destructor,
 and is passed as an argument by value, the convention is that the callee will
 destroy the object before returning.
 
+If a type is trivial for the purpose of calls, it is assumed to be trivially
+relocatable for the purpose of ``__is_trivially_relocatable``.
+
 Attribute ``trivial_abi`` has no effect in the following cases:
 
 - The class directly declares a virtual base or virtual methods.

diff  --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index e55244e1c3ac9..b9d5cd76d51d6 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -510,6 +510,7 @@ TYPE_TRAIT_1(__has_unique_object_representations,
 KEYWORD(__underlying_type   , KEYCXX)
 
 // Clang-only C++ Type Traits
+TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
 TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
 
 // Embarcadero Expression Traits

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 774b3e94159db..1c7499c3c237e 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2495,6 +2495,25 @@ bool QualType::isTriviallyCopyableType(const ASTContext 
) const {
   return false;
 }
 
+bool QualType::isTriviallyRelocatableType(const ASTContext ) const {
+  QualType BaseElementType = Context.getBaseElementType(*this);
+
+  if (BaseElementType->isIncompleteType()) {
+return false;
+  } else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
+return RD->canPassInRegisters();
+  } else {
+switch 

[clang] 852afed - Revert "[clang] Mark `trivial_abi` types as "trivially relocatable"."

2022-02-03 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2022-02-03T22:31:44+01:00
New Revision: 852afed5e0200b70047c28ccf4424a17089d17b0

URL: 
https://github.com/llvm/llvm-project/commit/852afed5e0200b70047c28ccf4424a17089d17b0
DIFF: 
https://github.com/llvm/llvm-project/commit/852afed5e0200b70047c28ccf4424a17089d17b0.diff

LOG: Revert "[clang] Mark `trivial_abi` types as "trivially relocatable"."

This reverts commit 19aa2db023c0128913da223d4fb02c474541ee22. It breaks
a PS4 buildbot.

Added: 


Modified: 
clang/docs/LanguageExtensions.rst
clang/include/clang/AST/Type.h
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/TokenKinds.def
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/SemaCXX/attr-trivial-abi.cpp
clang/test/SemaCXX/type-traits.cpp
clang/test/SemaObjCXX/arc-type-traits.mm
clang/test/SemaObjCXX/objc-weak-type-traits.mm

Removed: 




diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index e74539d650ce0..f848fb01d8c5e 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1365,11 +1365,6 @@ The following type trait primitives are supported by 
Clang. Those traits marked
 * ``__is_trivially_constructible`` (C++, GNU, Microsoft)
 * ``__is_trivially_copyable`` (C++, GNU, Microsoft)
 * ``__is_trivially_destructible`` (C++, MSVC 2013)
-* ``__is_trivially_relocatable`` (Clang): Returns true if moving an object
-  of the given type, and then destroying the source object, is known to be
-  functionally equivalent to copying the underlying bytes and then dropping the
-  source object on the floor. This is true of trivial types and types which
-  were made trivially relocatable via the ``clang::trivial_abi`` attribute.
 * ``__is_union`` (C++, GNU, Microsoft, Embarcadero)
 * ``__is_unsigned`` (C++, Embarcadero):
   Returns false for enumeration types. Note, before Clang 13, returned true for

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 3c71cbbb9c8f3..a69c0ae67d0a0 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -829,8 +829,6 @@ class QualType {
   /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
   bool isTriviallyCopyableType(const ASTContext ) const;
 
-  /// Return true if this is a trivially relocatable type.
-  bool isTriviallyRelocatableType(const ASTContext ) const;
 
   /// Returns true if it is a class and it might be dynamic.
   bool mayBeDynamicClass() const;

diff  --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index e12a0b259cc2e..efd2af1ab1df3 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -3295,9 +3295,6 @@ If a type is trivial for the purposes of calls, has a 
non-trivial destructor,
 and is passed as an argument by value, the convention is that the callee will
 destroy the object before returning.
 
-If a type is trivial for the purpose of calls, it is assumed to be trivially
-relocatable for the purpose of ``__is_trivially_relocatable``.
-
 Attribute ``trivial_abi`` has no effect in the following cases:
 
 - The class directly declares a virtual base or virtual methods.

diff  --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index b9d5cd76d51d6..e55244e1c3ac9 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -510,7 +510,6 @@ TYPE_TRAIT_1(__has_unique_object_representations,
 KEYWORD(__underlying_type   , KEYCXX)
 
 // Clang-only C++ Type Traits
-TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
 TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
 
 // Embarcadero Expression Traits

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 1c7499c3c237e..774b3e94159db 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2495,25 +2495,6 @@ bool QualType::isTriviallyCopyableType(const ASTContext 
) const {
   return false;
 }
 
-bool QualType::isTriviallyRelocatableType(const ASTContext ) const {
-  QualType BaseElementType = Context.getBaseElementType(*this);
-
-  if (BaseElementType->isIncompleteType()) {
-return false;
-  } else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
-return RD->canPassInRegisters();
-  } else {
-switch (isNonTrivialToPrimitiveDestructiveMove()) {
-case PCK_Trivial:
-  return !isDestructedType();
-case PCK_ARCStrong:
-  return true;
-default:
-  return false;
-}
-  }
-}
-
 bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext ) const {
   return !Context.getLangOpts().ObjCAutoRefCount &&
  Context.getLangOpts().ObjCWeak &&

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 

[clang-tools-extra] fd8fc5e - [clang-tidy] abseil-string-find-startswith: detect `s.rfind(z, 0) == 0`

2021-12-22 Thread Dmitri Gribenko via cfe-commits

Author: Ivan Gerasimov
Date: 2021-12-22T16:45:51+01:00
New Revision: fd8fc5e8d93849f4a2c8dea087690b1a0e6ea7df

URL: 
https://github.com/llvm/llvm-project/commit/fd8fc5e8d93849f4a2c8dea087690b1a0e6ea7df
DIFF: 
https://github.com/llvm/llvm-project/commit/fd8fc5e8d93849f4a2c8dea087690b1a0e6ea7df.diff

LOG: [clang-tidy] abseil-string-find-startswith: detect `s.rfind(z, 0) == 0`

Suggest converting `std::string::rfind()` calls to `absl::StartsWith()`
where possible.

Added: 


Modified: 
clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst
clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp 
b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
index 5741c0d505d51..e834c8a124590 100644
--- a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -40,7 +40,7 @@ void StringFindStartswithCheck::registerMatchers(MatchFinder 
*Finder) {
 
   auto StringFind = cxxMemberCallExpr(
   // .find()-call on a string...
-  callee(cxxMethodDecl(hasName("find"))),
+  callee(cxxMethodDecl(hasName("find")).bind("findfun")),
   on(hasType(StringType)),
   // ... with some search expression ...
   hasArgument(0, expr().bind("needle")),
@@ -55,6 +55,25 @@ void StringFindStartswithCheck::registerMatchers(MatchFinder 
*Finder) {
   ignoringParenImpCasts(StringFind.bind("findexpr"
   .bind("expr"),
   this);
+
+  auto StringRFind = cxxMemberCallExpr(
+  // .rfind()-call on a string...
+  callee(cxxMethodDecl(hasName("rfind")).bind("findfun")),
+  on(hasType(StringType)),
+  // ... with some search expression ...
+  hasArgument(0, expr().bind("needle")),
+  // ... and "0" as second argument.
+  hasArgument(1, ZeroLiteral));
+
+  Finder->addMatcher(
+  // Match [=!]= with either a zero or npos on one side and a string.rfind
+  // on the other.
+  binaryOperator(
+  hasAnyOperatorName("==", "!="),
+  hasOperands(ignoringParenImpCasts(ZeroLiteral),
+  ignoringParenImpCasts(StringRFind.bind("findexpr"
+  .bind("expr"),
+  this);
 }
 
 void StringFindStartswithCheck::check(const MatchFinder::MatchResult ) {
@@ -69,6 +88,11 @@ void StringFindStartswithCheck::check(const 
MatchFinder::MatchResult ) {
   const Expr *Haystack = Result.Nodes.getNodeAs("findexpr")
  ->getImplicitObjectArgument();
   assert(Haystack != nullptr);
+  const CXXMethodDecl *FindFun =
+  Result.Nodes.getNodeAs("findfun");
+  assert(FindFun != nullptr);
+
+  bool Rev = FindFun->getName().contains("rfind");
 
   if (ComparisonExpr->getBeginLoc().isMacroID())
 return;
@@ -86,10 +110,11 @@ void StringFindStartswithCheck::check(const 
MatchFinder::MatchResult ) {
   bool Neg = ComparisonExpr->getOpcode() == BO_NE;
 
   // Create the warning message and a FixIt hint replacing the original expr.
-  auto Diagnostic = diag(ComparisonExpr->getBeginLoc(),
- "use %select{absl::StartsWith|!absl::StartsWith}0 "
- "instead of find() %select{==|!=}0 0")
-<< Neg;
+  auto Diagnostic =
+  diag(ComparisonExpr->getBeginLoc(),
+   "use %select{absl::StartsWith|!absl::StartsWith}0 "
+   "instead of %select{find()|rfind()}1 %select{==|!=}0 0")
+  << Neg << Rev;
 
   Diagnostic << FixItHint::CreateReplacement(
   ComparisonExpr->getSourceRange(),

diff  --git 
a/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst 
b/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst
index 43f35ac66c8ac..8224c37a087b8 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst
@@ -3,14 +3,15 @@
 abseil-string-find-startswith
 =
 
-Checks whether a ``std::string::find()`` result is compared with 0, and
-suggests replacing with ``absl::StartsWith()``. This is both a readability and
-performance issue.
+Checks whether a ``std::string::find()`` or ``std::string::rfind()`` result is
+compared with 0, and suggests replacing with ``absl::StartsWith()``. This is
+both a readability and performance issue.
 
 .. code-block:: c++
 
   string s = "...";
   if (s.find("Hello World") == 0) { /* do something */ }
+  if (s.rfind("Hello World", 0) == 0) { /* do something */ }
 
 becomes
 
@@ -19,6 +20,7 @@ becomes
 
   string s = "...";
   if (absl::StartsWith(s, "Hello World")) { /* do something */ }
+  if (absl::StartsWith(s, "Hello World")) { /* do something */ }
 

[clang] 8dcaf3a - [clang][dataflow] Implement a basic algorithm for dataflow analysis

2021-12-10 Thread Dmitri Gribenko via cfe-commits

Author: Stanislav Gatev
Date: 2021-12-10T11:44:49+01:00
New Revision: 8dcaf3aa0bf25508700a7452ed963c1487221dfd

URL: 
https://github.com/llvm/llvm-project/commit/8dcaf3aa0bf25508700a7452ed963c1487221dfd
DIFF: 
https://github.com/llvm/llvm-project/commit/8dcaf3aa0bf25508700a7452ed963c1487221dfd.diff

LOG: [clang][dataflow] Implement a basic algorithm for dataflow analysis

This is part of the implementation of the dataflow analysis framework.
See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev.

Reviewed By: xazax.hun, gribozavr2

Differential Revision: https://reviews.llvm.org/D115235

Added: 
clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Modified: 
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
clang/unittests/Analysis/CMakeLists.txt

Removed: 




diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 69a5c2e47b66d..4a3c0239f8e12 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -15,11 +15,20 @@
 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
 
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+
 namespace clang {
 namespace dataflow {
 
 /// Holds the state of the program (store and heap) at a given program point.
-class Environment {};
+class Environment {
+public:
+  bool operator==(const Environment &) const { return true; }
+
+  LatticeJoinEffect join(const Environment &) {
+return LatticeJoinEffect::Unchanged;
+  }
+};
 
 } // namespace dataflow
 } // namespace clang

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h 
b/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
index 90095735ad3d5..52d84eb13c568 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
@@ -61,11 +61,12 @@ struct ReversePostOrderCompare {
 /// the same block multiple times at once.
 struct ForwardDataflowWorklist
 : DataflowWorklistBase {
+  ForwardDataflowWorklist(const CFG , PostOrderCFGView *POV)
+  : DataflowWorklistBase(Cfg, POV,
+ ReversePostOrderCompare{POV->getComparator()}) {}
+
   ForwardDataflowWorklist(const CFG , AnalysisDeclContext )
-  : DataflowWorklistBase(
-Cfg, Ctx.getAnalysis(),
-ReversePostOrderCompare{
-Ctx.getAnalysis()->getComparator()}) {}
+  : ForwardDataflowWorklist(Cfg, Ctx.getAnalysis()) {}
 
   void enqueueSuccessors(const CFGBlock *Block) {
 for (auto B : Block->succs())

diff  --git 
a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h 
b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
index 9448b911f4718..55fae246da795 100644
--- a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -76,6 +76,20 @@ struct TypeErasedDataflowAnalysisState {
   Environment Env;
 };
 
+/// Transfers the state of a basic block by evaluating each of its statements 
in
+/// the context of `Analysis` and the states of its predecessors that are
+/// available in `BlockStates`.
+///
+/// Requirements:
+///
+///   All predecessors of `Block` except those with loop back edges must have
+///   already been transferred. States in `BlockStates` that are set to
+///   `llvm::None` represent basic blocks that are not evaluated yet.
+TypeErasedDataflowAnalysisState transferBlock(
+std::vector> ,
+const CFGBlock , const Environment ,
+TypeErasedDataflowAnalysis );
+
 /// Performs dataflow analysis and returns a mapping from basic block IDs to
 /// dataflow analysis states that model the respective basic blocks. Indices
 /// of the returned vector correspond to basic block IDs.

diff  --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index bb7eb99710681..45afd59728e14 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,15 +11,77 @@
 //
 
//===--===//
 
+#include 
 #include 
 
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
 #include "clang/Analysis/CFG.h"
 #include 

[clang] efb284c - [clang-format] Fixed an unused variable warning

2021-09-24 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2021-09-24T10:37:04+02:00
New Revision: efb284c07e97776e01933f470afb5215a561db3e

URL: 
https://github.com/llvm/llvm-project/commit/efb284c07e97776e01933f470afb5215a561db3e
DIFF: 
https://github.com/llvm/llvm-project/commit/efb284c07e97776e01933f470afb5215a561db3e.diff

LOG: [clang-format] Fixed an unused variable warning

Added: 


Modified: 
clang/lib/Format/QualifierAlignmentFixer.cpp

Removed: 




diff  --git a/clang/lib/Format/QualifierAlignmentFixer.cpp 
b/clang/lib/Format/QualifierAlignmentFixer.cpp
index 6e2b53b711f26..4a42442ca24bc 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -406,9 +406,9 @@ void QualifierAlignmentFixer::PrepareLeftRightOrdering(
   // Depending on the position of type in the order you need
   // To iterate forward or backward through the order list as qualifier
   // can push through each other.
-  auto type = std::find(Order.begin(), Order.end(), "type");
   // The Order list must define the position of "type" to signify
-  assert(type != Order.end() && "QualifierOrder must contain type");
+  assert(std::find(Order.begin(), Order.end(), "type") != Order.end() &&
+ "QualifierOrder must contain type");
   // Split the Order list by type and reverse the left side.
 
   bool left = true;



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


[clang] 595c375 - Fix the const overload of IgnoreExprNodes

2021-04-13 Thread Dmitri Gribenko via cfe-commits

Author: Jesse Zhang
Date: 2021-04-13T17:59:59+02:00
New Revision: 595c3758e47042c876e7390d09642ea050ba6dbf

URL: 
https://github.com/llvm/llvm-project/commit/595c3758e47042c876e7390d09642ea050ba6dbf
DIFF: 
https://github.com/llvm/llvm-project/commit/595c3758e47042c876e7390d09642ea050ba6dbf.diff

LOG: Fix the const overload of IgnoreExprNodes

The existing code causes an infinite recursion. This is likely an
oversight of commit c0e5e3fbfa504c37 [1] where the intent must have been
to call the non-const overload.

[1] https://reviews.llvm.org/D87278

Reviewed By: gribozavr2

Differential Revision: https://reviews.llvm.org/D100347

Added: 


Modified: 
clang/include/clang/AST/IgnoreExpr.h

Removed: 




diff  --git a/clang/include/clang/AST/IgnoreExpr.h 
b/clang/include/clang/AST/IgnoreExpr.h
index 1c2b538e5b635..b2f53d1d2a798 100644
--- a/clang/include/clang/AST/IgnoreExpr.h
+++ b/clang/include/clang/AST/IgnoreExpr.h
@@ -41,7 +41,7 @@ template  Expr *IgnoreExprNodes(Expr *E, 
FnTys &&... Fns) {
 
 template 
 const Expr *IgnoreExprNodes(const Expr *E, FnTys &&...Fns) {
-  return const_cast(IgnoreExprNodes(E, std::forward(Fns)...));
+  return IgnoreExprNodes(const_cast(E), std::forward(Fns)...);
 }
 
 inline Expr *IgnoreImplicitCastsSingleStep(Expr *E) {



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


[clang] 9cd7c41 - [analyzer] Don't include private gtest headers

2021-03-22 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2021-03-22T13:31:38+01:00
New Revision: 9cd7c4130635a6f0c94046f529fb1ee19118bbfb

URL: 
https://github.com/llvm/llvm-project/commit/9cd7c4130635a6f0c94046f529fb1ee19118bbfb
DIFF: 
https://github.com/llvm/llvm-project/commit/9cd7c4130635a6f0c94046f529fb1ee19118bbfb.diff

LOG: [analyzer] Don't include private gtest headers

Added: 


Modified: 
clang/unittests/StaticAnalyzer/RangeSetTest.cpp

Removed: 




diff  --git a/clang/unittests/StaticAnalyzer/RangeSetTest.cpp 
b/clang/unittests/StaticAnalyzer/RangeSetTest.cpp
index aeeff47a9af9..5be2ee3fc520 100644
--- a/clang/unittests/StaticAnalyzer/RangeSetTest.cpp
+++ b/clang/unittests/StaticAnalyzer/RangeSetTest.cpp
@@ -13,7 +13,6 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest-typed-test.h"
 #include "gtest/gtest.h"
 
 using namespace clang;



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


[clang] 37c74df - Revert "[c++17] Implement P0145R3 during constant evaluation."

2020-10-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-10-06T15:49:44+02:00
New Revision: 37c74dfe72ecf4e7def22702c5a944682a7865df

URL: 
https://github.com/llvm/llvm-project/commit/37c74dfe72ecf4e7def22702c5a944682a7865df
DIFF: 
https://github.com/llvm/llvm-project/commit/37c74dfe72ecf4e7def22702c5a944682a7865df.diff

LOG: Revert "[c++17] Implement P0145R3 during constant evaluation."

This reverts commit ded79be63555f4e5bfdb0db27ef22b71fe568474. It causes
a crash (I sent the crash reproducer directly to the author).

Added: 


Modified: 
clang/lib/AST/ExprConstant.cpp
clang/test/SemaCXX/constant-expression-cxx1z.cpp
clang/www/cxx_status.html

Removed: 




diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 49ad01f27545..4460e3a17e6d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1856,12 +1856,8 @@ void CallStackFrame::describe(raw_ostream ) {
   Out << ", ";
 
 const ParmVarDecl *Param = *I;
-if (Arguments) {
-  const APValue  = Arguments[ArgIndex];
-  Arg.printPretty(Out, Info.Ctx, Param->getType());
-} else {
-  Out << "<...>";
-}
+const APValue  = Arguments[ArgIndex];
+Arg.printPretty(Out, Info.Ctx, Param->getType());
 
 if (ArgIndex == 0 && IsMemberCall)
   Out << "->" << *Callee << '(';
@@ -5796,8 +5792,6 @@ typedef SmallVector ArgVector;
 /// EvaluateArgs - Evaluate the arguments to a function call.
 static bool EvaluateArgs(ArrayRef Args, ArgVector ,
  EvalInfo , const FunctionDecl *Callee) {
-  ArgValues.resize(Args.size());
-
   bool Success = true;
   llvm::SmallBitVector ForbiddenNullArgs;
   if (Callee->hasAttr()) {
@@ -5815,6 +5809,8 @@ static bool EvaluateArgs(ArrayRef Args, 
ArgVector ,
 }
 }
   }
+  // FIXME: This is the wrong evaluation order for an assignment operator
+  // called via operator syntax.
   for (unsigned Idx = 0; Idx < Args.size(); Idx++) {
 if (!Evaluate(ArgValues[Idx], Info, Args[Idx])) {
   // If we're checking for a potential constant expression, evaluate all
@@ -5838,13 +5834,17 @@ static bool EvaluateArgs(ArrayRef Args, 
ArgVector ,
 /// Evaluate a function call.
 static bool HandleFunctionCall(SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
-   ArrayRef Args, APValue *ArgValues,
-   const Stmt *Body, EvalInfo ,
-   APValue , const LValue *ResultSlot) {
+   ArrayRef Args, const Stmt *Body,
+   EvalInfo , APValue ,
+   const LValue *ResultSlot) {
+  ArgVector ArgValues(Args.size());
+  if (!EvaluateArgs(Args, ArgValues, Info, Callee))
+return false;
+
   if (!Info.CheckCallLimit(CallLoc))
 return false;
 
-  CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues);
+  CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data());
 
   // For a trivial copy or move assignment, perform an APValue copy. This is
   // essential for unions, where the operations performed by the assignment
@@ -7293,8 +7293,6 @@ class ExprEvaluatorBase
 auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
 bool HasQualifier = false;
 
-ArgVector ArgValues;
-
 // Extract function decl and 'this' pointer from the callee.
 if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
   const CXXMethodDecl *Member = nullptr;
@@ -7343,22 +7341,6 @@ class ExprEvaluatorBase
 return Error(E);
   }
 
-  // For an (overloaded) assignment expression, evaluate the RHS before the
-  // LHS.
-  auto *OCE = dyn_cast(E);
-  if (OCE && OCE->isAssignmentOp()) {
-assert(Args.size() == 2 && "wrong number of arguments in assignment");
-if (isa(FD)) {
-  // Args[0] is the object argument.
-  if (!EvaluateArgs({Args[1]}, ArgValues, Info, FD))
-return false;
-} else {
-  if (!EvaluateArgs({Args[1], Args[0]}, ArgValues, Info, FD))
-return false;
-  std::swap(ArgValues[0], ArgValues[1]);
-}
-  }
-
   // Overloaded operator calls to member functions are represented as 
normal
   // calls with '*this' as the first argument.
   const CXXMethodDecl *MD = dyn_cast(FD);
@@ -7421,11 +7403,6 @@ class ExprEvaluatorBase
 } else
   return Error(E);
 
-// Evaluate the arguments now if we've not already done so.
-if (ArgValues.empty() && !Args.empty() &&
-!EvaluateArgs(Args, ArgValues, Info, FD))
-  return false;
-
 SmallVector CovariantAdjustmentPath;
 if (This) {
   auto *NamedMember = dyn_cast(FD);
@@ -7447,7 +7424,6 @@ class ExprEvaluatorBase
 // Destructor calls are 
diff erent enough that they have their own codepath.
 if (auto 

[clang] e10df77 - Fix clang Wrange-loop-analysis in BuildTree.cpp

2020-09-11 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-09-12T01:07:54+02:00
New Revision: e10df779f097e3a1fb02d901117ce71a5dd9dda2

URL: 
https://github.com/llvm/llvm-project/commit/e10df779f097e3a1fb02d901117ce71a5dd9dda2
DIFF: 
https://github.com/llvm/llvm-project/commit/e10df779f097e3a1fb02d901117ce71a5dd9dda2.diff

LOG: Fix clang Wrange-loop-analysis in BuildTree.cpp

Building on Mac OS with clang 12:

```
jhemphill@jhemphill-mbp build % clang --version
Apple clang version 12.0.0 (clang-1200.0.26.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
```

yields one warning:

```
/Users/jhemphill/oss/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp:1126:22:
 warning: loop variable 'Arg' is always a copy because the range of type 
'llvm::iterator_range >' does not return a reference [-Wrange-loop-analysis]
for (const auto  : Args) {
 ^
/Users/jhemphill/oss/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp:1126:10:
 note: use non-reference type 'clang::Expr *'
for (const auto  : Args) {
```

It appears that `Arg` is an `Expr*`, passed by value rather than by const 
reference.

Reviewed By: eduucaldas, gribozavr2

Differential Revision: https://reviews.llvm.org/D87482

Added: 


Modified: 
clang/lib/Tooling/Syntax/BuildTree.cpp

Removed: 




diff  --git a/clang/lib/Tooling/Syntax/BuildTree.cpp 
b/clang/lib/Tooling/Syntax/BuildTree.cpp
index dab1457fbdba..3e0573ac4ffc 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -1126,7 +1126,7 @@ class BuildTreeVisitor : public 
RecursiveASTVisitor {
   syntax::CallArguments *
   buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs) {
 auto Args = dropDefaultArgs(ArgsAndDefaultArgs);
-for (const auto  : Args) {
+for (auto *Arg : Args) {
   Builder.markExprChild(Arg, syntax::NodeRole::ListElement);
   const auto *DelimiterToken =
   std::next(Builder.findToken(Arg->getEndLoc()));



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


[clang] a5b8757 - Introduce ns_error_domain attribute.

2020-08-13 Thread Dmitri Gribenko via cfe-commits

Author: Michael Forster
Date: 2020-08-13T15:05:12+02:00
New Revision: a5b8757506b07e3091fe243b6c1e004220d3cba3

URL: 
https://github.com/llvm/llvm-project/commit/a5b8757506b07e3091fe243b6c1e004220d3cba3
DIFF: 
https://github.com/llvm/llvm-project/commit/a5b8757506b07e3091fe243b6c1e004220d3cba3.diff

LOG: Introduce ns_error_domain attribute.

ns_error_domain can be used by, e.g. NS_ERROR_ENUM, in order to
identify a global declaration representing the domain constant.

Introduces the attribute, Sema handling, diagnostics, and test case.

This is cherry-picked from 
https://github.com/llvm/llvm-project-staging/commit/a14779f504b02ad0e4dbc39d6d10cadc7ed4cfd0
and adapted to updated Clang APIs.

Reviewed By: gribozavr2, aaron.ballman

Differential Revision: https://reviews.llvm.org/D84005

Added: 
clang/test/Sema/ns_error_enum.m

Modified: 
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/AST/ast-print-attr.c
clang/test/Misc/pragma-attribute-supported-attributes-list.test
clang/utils/TableGen/ClangAttrEmitter.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 3d8ad705f91f..f525d3566dbb 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1878,6 +1878,13 @@ def ObjCBridgeRelated : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def NSErrorDomain : InheritableAttr {
+  let Spellings = [GNU<"ns_error_domain">];
+  let Subjects = SubjectList<[Enum], ErrorDiag>;
+  let Args = [DeclArgument];
+  let Documentation = [NSErrorDomainDocs];
+}
+
 def NSReturnsRetained : DeclOrTypeAttr {
   let Spellings = [Clang<"ns_returns_retained">];
 //  let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;

diff  --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 83990721d7f7..29ad179e46e9 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -3339,6 +3339,38 @@ arguments, with arbitrary offsets.
   }];
 }
 
+def NSErrorDomainDocs : Documentation {
+  let Category = DocCatDecl;
+  let Content = [{
+In Cocoa frameworks in Objective-C, one can group related error codes in enums
+and categorize these enums with error domains.
+
+The ``ns_error_domain`` attribute indicates a global ``NSString`` constant
+representing the error domain that an error code belongs to. For pointer
+uniqueness and code size this is a constant symbol, not a literal.
+
+The domain and error code need to be used together. The ``ns_error_domain``
+attribute links error codes to their domain at the source level.
+
+This metadata is useful for documentation purposes, for static analysis, and 
for
+improving interoperability between Objective-C and Swift. It is not used for
+code generation in Objective-C.
+
+For example:
+
+  .. code-block:: objc
+
+#define NS_ERROR_ENUM(_type, _name, _domain)  \
+  enum _name : _type _name; enum __attribute__((ns_error_domain(_domain))) 
_name : _type
+
+extern NSString *const MyErrorDomain;
+typedef NS_ERROR_ENUM(unsigned char, MyErrorEnum, MyErrorDomain) {
+  MyErrFirst,
+  MyErrSecond,
+};
+  }];
+}
+
 def OMPDeclareSimdDocs : Documentation {
   let Category = DocCatFunction;
   let Heading = "#pragma omp declare simd";

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f2e939da3050..e3edddf6a3f2 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9476,6 +9476,11 @@ def err_nsconsumed_attribute_mismatch : Error<
 def err_nsreturns_retained_attribute_mismatch : Error<
   "overriding method has mismatched ns_returns_%select{not_retained|retained}0"
   " attributes">;
+def err_nserrordomain_invalid_decl : Error<
+  "domain argument %select{|%1 }0does not refer to global constant">;
+def err_nserrordomain_wrong_type : Error<
+  "domain argument %0 does not point to an NSString constant">;
+
 def warn_nsconsumed_attribute_mismatch : Warning<
   err_nsconsumed_attribute_mismatch.Text>, InGroup;
 def warn_nsreturns_retained_attribute_mismatch : Warning<

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d46c791b0e3a..bb19bd097564 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/Mangle.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetBuiltins.h"
@@ -30,12 +31,15 @@
 #include "clang/Sema/DelayedDiagnostic.h"
 #include "clang/Sema/Initialization.h"
 #include 

[Differential] D83966: Enable the test for hasArraySize() AST matcher in all language modes

2020-07-20 Thread Dmitri Gribenko via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb6073ee9ae84: Enable the test for hasArraySize() AST matcher 
in all language modes (authored by gribozavr).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83966/new/


  https://reviews.llvm.org/D83966

Files:
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp



Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -3219,13 +3219,13 @@
 }
 
 TEST_P(ASTMatchersTest, HasArraySize) {
-  if (GetParam().Language != Lang_CXX03) {
-// FIXME: Fix this test to work in all C++ language modes.
+  if (!GetParam().isCXX()) {
 return;
   }
 
   EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];",
-  cxxNewExpr(hasArraySize(integerLiteral(equals(10));
+  cxxNewExpr(hasArraySize(
+  
ignoringParenImpCasts(integerLiteral(equals(10)));
 }
 
 TEST_P(ASTMatchersTest, HasDefinition_MatchesStructDefinition) {


Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -3219,13 +3219,13 @@
 }
 
 TEST_P(ASTMatchersTest, HasArraySize) {
-  if (GetParam().Language != Lang_CXX03) {
-// FIXME: Fix this test to work in all C++ language modes.
+  if (!GetParam().isCXX()) {
 return;
   }
 
   EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];",
-  cxxNewExpr(hasArraySize(integerLiteral(equals(10));
+  cxxNewExpr(hasArraySize(
+  ignoringParenImpCasts(integerLiteral(equals(10)));
 }
 
 TEST_P(ASTMatchersTest, HasDefinition_MatchesStructDefinition) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] b6073ee - Enable the test for hasArraySize() AST matcher in all language modes

2020-07-20 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-20T10:23:00+02:00
New Revision: b6073ee9ae842d1999fd7798a0aac0f8427d6aea

URL: 
https://github.com/llvm/llvm-project/commit/b6073ee9ae842d1999fd7798a0aac0f8427d6aea
DIFF: 
https://github.com/llvm/llvm-project/commit/b6073ee9ae842d1999fd7798a0aac0f8427d6aea.diff

LOG: Enable the test for hasArraySize() AST matcher in all language modes

Summary:
In C++11 and later Clang generates an implicit conversion from int to
size_t in the AST.

Reviewers: ymandel, hokein

Reviewed By: hokein

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83966

Added: 


Modified: 
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Removed: 




diff  --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp 
b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 36e92c632c03..4bd50191e163 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -3219,13 +3219,13 @@ TEST_P(ASTMatchersTest, IsArray) {
 }
 
 TEST_P(ASTMatchersTest, HasArraySize) {
-  if (GetParam().Language != Lang_CXX03) {
-// FIXME: Fix this test to work in all C++ language modes.
+  if (!GetParam().isCXX()) {
 return;
   }
 
   EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];",
-  cxxNewExpr(hasArraySize(integerLiteral(equals(10));
+  cxxNewExpr(hasArraySize(
+  
ignoringParenImpCasts(integerLiteral(equals(10)));
 }
 
 TEST_P(ASTMatchersTest, HasDefinition_MatchesStructDefinition) {



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


[clang] 4f244c4 - Use TestClangConfig in AST Matchers tests and run them in more configurations

2020-07-16 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-16T18:36:53+02:00
New Revision: 4f244c4b42b096a55f2e7f719e1101c6fd26c034

URL: 
https://github.com/llvm/llvm-project/commit/4f244c4b42b096a55f2e7f719e1101c6fd26c034
DIFF: 
https://github.com/llvm/llvm-project/commit/4f244c4b42b096a55f2e7f719e1101c6fd26c034.diff

LOG: Use TestClangConfig in AST Matchers tests and run them in more 
configurations

Summary:
I am changing tests for AST Matchers to run in multiple language standards
versions, and under multiple triples that have different behavior with regards
to templates. This change is similar to https://reviews.llvm.org/D82179.

To keep the size of the patch manageable, in this patch I'm only migrating one
file to get the process started and get feedback on this approach.

Reviewers: ymandel

Reviewed By: ymandel

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83868

Added: 


Modified: 
clang/include/clang/Testing/TestClangConfig.h
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
clang/unittests/ASTMatchers/ASTMatchersTest.h

Removed: 




diff  --git a/clang/include/clang/Testing/TestClangConfig.h 
b/clang/include/clang/Testing/TestClangConfig.h
index eefa36dc2ebb..5d6be4f65d0a 100644
--- a/clang/include/clang/Testing/TestClangConfig.h
+++ b/clang/include/clang/Testing/TestClangConfig.h
@@ -51,6 +51,8 @@ struct TestClangConfig {
 return Language == Lang_CXX17 || Language == Lang_CXX20;
   }
 
+  bool isCXX20OrLater() const { return Language == Lang_CXX20; }
+
   bool supportsCXXDynamicExceptionSpecification() const {
 return Language == Lang_CXX03 || Language == Lang_CXX11 ||
Language == Lang_CXX14;

diff  --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp 
b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index c249410201ba..36e92c632c03 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -18,7 +18,7 @@
 namespace clang {
 namespace ast_matchers {
 
-TEST(IsExpandedFromMacro, ShouldMatchInFile) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesInFile) {
   StringRef input = R"cc(
 #define MY_MACRO(a) (4 + (a))
 void Test() { MY_MACRO(4); }
@@ -26,7 +26,7 @@ TEST(IsExpandedFromMacro, ShouldMatchInFile) {
   EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO";
 }
 
-TEST(IsExpandedFromMacro, ShouldMatchNested) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesNested) {
   StringRef input = R"cc(
 #define MY_MACRO(a) (4 + (a))
 #define WRAPPER(a) MY_MACRO(a)
@@ -35,7 +35,7 @@ TEST(IsExpandedFromMacro, ShouldMatchNested) {
   EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO";
 }
 
-TEST(IsExpandedFromMacro, ShouldMatchIntermediate) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesIntermediate) {
   StringRef input = R"cc(
 #define IMPL(a) (4 + (a))
 #define MY_MACRO(a) IMPL(a)
@@ -45,7 +45,7 @@ TEST(IsExpandedFromMacro, ShouldMatchIntermediate) {
   EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO";
 }
 
-TEST(IsExpandedFromMacro, ShouldMatchTransitive) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesTransitive) {
   StringRef input = R"cc(
 #define MY_MACRO(a) (4 + (a))
 #define WRAPPER(a) MY_MACRO(a)
@@ -54,7 +54,7 @@ TEST(IsExpandedFromMacro, ShouldMatchTransitive) {
   EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("WRAPPER";
 }
 
-TEST(IsExpandedFromMacro, ShouldMatchArgument) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesArgument) {
   StringRef input = R"cc(
 #define MY_MACRO(a) (4 + (a))
 void Test() {
@@ -65,9 +65,9 @@ TEST(IsExpandedFromMacro, ShouldMatchArgument) {
   EXPECT_TRUE(matches(input, declRefExpr(isExpandedFromMacro("MY_MACRO";
 }
 
-// Like IsExpandedFromMacroShouldMatchArgumentMacro, but the argument is itself
-// a macro.
-TEST(IsExpandedFromMacro, ShouldMatchArgumentMacroExpansion) {
+// Like IsExpandedFromMacro_MatchesArgument, but the argument is itself a
+// macro.
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesArgumentMacroExpansion) {
   StringRef input = R"cc(
 #define MY_MACRO(a) (4 + (a))
 #define IDENTITY(a) (a)
@@ -78,7 +78,7 @@ TEST(IsExpandedFromMacro, ShouldMatchArgumentMacroExpansion) {
   EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("IDENTITY";
 }
 
-TEST(IsExpandedFromMacro, ShouldMatchWhenInArgument) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesWhenInArgument) {
   StringRef input = R"cc(
 #define MY_MACRO(a) (4 + (a))
 #define IDENTITY(a) (a)
@@ -89,7 +89,7 @@ TEST(IsExpandedFromMacro, ShouldMatchWhenInArgument) {
   EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO";
 }
 
-TEST(IsExpandedFromMacro, ShouldMatchObjectMacro) {
+TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesObjectMacro) {
   StringRef input = 

[clang] 8978032 - Fix test for the hasExternalFormalLinkage matcher

2020-07-14 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-14T15:44:53+02:00
New Revision: 8978032a17cd0f1c3925ecb1752fdf59de7f7967

URL: 
https://github.com/llvm/llvm-project/commit/8978032a17cd0f1c3925ecb1752fdf59de7f7967
DIFF: 
https://github.com/llvm/llvm-project/commit/8978032a17cd0f1c3925ecb1752fdf59de7f7967.diff

LOG: Fix test for the hasExternalFormalLinkage matcher

Summary:
Names of local variables have no linkage (see C++20 [basic.link] p8).

Names of variables in unnamed namespace have internal linkage (see C++20
[basic.link] p4).

Reviewers: aaron.ballman, rsmith, ymandel

Reviewed By: ymandel

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83700

Added: 


Modified: 
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Removed: 




diff  --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp 
b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 687908043a8d..c249410201ba 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2534,19 +2534,16 @@ TEST(NullPointerConstants, Basic) {
 }
 
 TEST(HasExternalFormalLinkage, Basic) {
-  EXPECT_TRUE(matches("int a = 0;", namedDecl(hasExternalFormalLinkage(;
-  EXPECT_TRUE(
-  notMatches("static int a = 0;", namedDecl(hasExternalFormalLinkage(;
+  EXPECT_TRUE(matches("int a = 0;",
+  namedDecl(hasName("a"), hasExternalFormalLinkage(;
+  EXPECT_TRUE(notMatches("static int a = 0;",
+ namedDecl(hasName("a"), hasExternalFormalLinkage(;
   EXPECT_TRUE(notMatches("static void f(void) { int a = 0; }",
- namedDecl(hasExternalFormalLinkage(;
-  EXPECT_TRUE(matches("void f(void) { int a = 0; }",
-  namedDecl(hasExternalFormalLinkage(;
-
-  // Despite having internal semantic linkage, the anonymous namespace member
-  // has external linkage because the member has a unique name in all
-  // translation units.
-  EXPECT_TRUE(matches("namespace { int a = 0; }",
-  namedDecl(hasExternalFormalLinkage(;
+ namedDecl(hasName("a"), hasExternalFormalLinkage(;
+  EXPECT_TRUE(notMatches("void f(void) { int a = 0; }",
+ namedDecl(hasName("a"), hasExternalFormalLinkage(;
+  EXPECT_TRUE(notMatches("namespace { int a = 0; }",
+ namedDecl(hasName("a"), hasExternalFormalLinkage(;
 }
 
 TEST(HasDefaultArgument, Basic) {



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


[clang] 3cca818 - Refactored NumericLiteralParser to not require a Preprocessor

2020-07-09 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-09T17:33:58+02:00
New Revision: 3cca818efabbccdde36b06609cf75ee7caa8e012

URL: 
https://github.com/llvm/llvm-project/commit/3cca818efabbccdde36b06609cf75ee7caa8e012
DIFF: 
https://github.com/llvm/llvm-project/commit/3cca818efabbccdde36b06609cf75ee7caa8e012.diff

LOG: Refactored NumericLiteralParser to not require a Preprocessor

Summary:
We would like to use NumericLiteralParser in the implementation of the
syntax tree builder, and plumbing a preprocessor there seems
inconvenient and superfluous.

Reviewers: eduucaldas

Reviewed By: eduucaldas

Subscribers: gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83480

Added: 


Modified: 
clang/include/clang/Lex/LiteralSupport.h
clang/lib/Lex/LiteralSupport.cpp
clang/lib/Lex/PPExpressions.cpp
clang/lib/Lex/Preprocessor.cpp
clang/lib/Sema/SemaExpr.cpp

Removed: 




diff  --git a/clang/include/clang/Lex/LiteralSupport.h 
b/clang/include/clang/Lex/LiteralSupport.h
index 6829771b2830..0c4f0fe277b7 100644
--- a/clang/include/clang/Lex/LiteralSupport.h
+++ b/clang/include/clang/Lex/LiteralSupport.h
@@ -40,7 +40,9 @@ void expandUCNs(SmallVectorImpl , StringRef Input);
 /// of a ppnumber, classifying it as either integer, floating, or erroneous,
 /// determines the radix of the value and can convert it to a useful value.
 class NumericLiteralParser {
-  Preprocessor  // needed for diagnostics
+  const SourceManager 
+  const LangOptions 
+  DiagnosticsEngine 
 
   const char *const ThisTokBegin;
   const char *const ThisTokEnd;
@@ -54,9 +56,9 @@ class NumericLiteralParser {
   SmallString<32> UDSuffixBuf;
 
 public:
-  NumericLiteralParser(StringRef TokSpelling,
-   SourceLocation TokLoc,
-   Preprocessor );
+  NumericLiteralParser(StringRef TokSpelling, SourceLocation TokLoc,
+   const SourceManager , const LangOptions ,
+   const TargetInfo , DiagnosticsEngine );
   bool hadError : 1;
   bool isUnsigned : 1;
   bool isLong : 1;  // This is *not* set for long long.

diff  --git a/clang/lib/Lex/LiteralSupport.cpp 
b/clang/lib/Lex/LiteralSupport.cpp
index f44614b4bec4..eb16bc8c7da2 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -525,8 +525,12 @@ static void EncodeUCNEscape(const char *ThisTokBegin, 
const char *,
 ///
 NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
SourceLocation TokLoc,
-   Preprocessor )
-  : PP(PP), ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) {
+   const SourceManager ,
+   const LangOptions ,
+   const TargetInfo ,
+   DiagnosticsEngine )
+: SM(SM), LangOpts(LangOpts), Diags(Diags),
+  ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) {
 
   // This routine assumes that the range begin/end matches the regex for 
integer
   // and FP constants (specifically, the 'pp-number' regex), and assumes that
@@ -572,7 +576,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   checkSeparator(TokLoc, s, CSK_AfterDigits);
 
   // Initial scan to lookahead for fixed point suffix.
-  if (PP.getLangOpts().FixedPoint) {
+  if (LangOpts.FixedPoint) {
 for (const char *c = s; c != ThisTokEnd; ++c) {
   if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') {
 saw_fixed_point_suffix = true;
@@ -592,14 +596,16 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
 switch (*s) {
 case 'R':
 case 'r':
-  if (!PP.getLangOpts().FixedPoint) break;
+  if (!LangOpts.FixedPoint)
+break;
   if (isFract || isAccum) break;
   if (!(saw_period || saw_exponent)) break;
   isFract = true;
   continue;
 case 'K':
 case 'k':
-  if (!PP.getLangOpts().FixedPoint) break;
+  if (!LangOpts.FixedPoint)
+break;
   if (isFract || isAccum) break;
   if (!(saw_period || saw_exponent)) break;
   isAccum = true;
@@ -607,7 +613,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
 case 'h':  // FP Suffix for "half".
 case 'H':
   // OpenCL Extension v1.2 s9.5 - h or H suffix for half type.
-  if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break;
+  if (!(LangOpts.Half || LangOpts.FixedPoint))
+break;
   if (isIntegerLiteral()) break;  // Error for integer constant.
   if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
   isHalf = true;
@@ -621,8 +628,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   // CUDA host and device may have 
diff erent 

[clang] 8e750b1 - Make RecursiveASTVisitor call WalkUpFrom for operators when the data recursion queue is absent

2020-07-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-06T13:38:01+02:00
New Revision: 8e750b1f0a2b6b5174dc49adf20e6f863c28e3cd

URL: 
https://github.com/llvm/llvm-project/commit/8e750b1f0a2b6b5174dc49adf20e6f863c28e3cd
DIFF: 
https://github.com/llvm/llvm-project/commit/8e750b1f0a2b6b5174dc49adf20e6f863c28e3cd.diff

LOG: Make RecursiveASTVisitor call WalkUpFrom for operators when the data 
recursion queue is absent

Reviewers: eduucaldas, ymandel, rsmith

Reviewed By: eduucaldas

Subscribers: gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82889

Added: 


Modified: 
clang/include/clang/AST/RecursiveASTVisitor.h
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index 9d93f1e99666..0d7c2b81512c 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -416,6 +416,8 @@ template  class RecursiveASTVisitor {
 if (!getDerived().shouldTraversePostOrder())   
\
   TRY_TO(WalkUpFromUnary##NAME(S));
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr());  
\
+if (!Queue && getDerived().shouldTraversePostOrder())  
\
+  TRY_TO(WalkUpFromUnary##NAME(S));
\
 return true;   
\
   }
\
   bool WalkUpFromUnary##NAME(UnaryOperator *S) {   
\
@@ -437,6 +439,8 @@ template  class RecursiveASTVisitor {
   TRY_TO(WalkUpFromBin##NAME(S));  
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS());  
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS());  
\
+if (!Queue && getDerived().shouldTraversePostOrder())  
\
+  TRY_TO(WalkUpFromBin##NAME(S));  
\
 return true;   
\
   }
\
   bool WalkUpFromBin##NAME(BINOP_TYPE *S) {
\

diff  --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp 
b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
index 0a4e9aa1e9e8..70c7eb37ad4c 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
@@ -606,14 +606,13 @@ TraverseUnaryMinus UnaryOperator(-)
 WalkUpFromStmt IntegerLiteral(3)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromStmt for
-  // UnaryOperator(-).
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
 WalkUpFromStmt IntegerLiteral(1)
 TraverseUnaryMinus UnaryOperator(-)
   WalkUpFromStmt IntegerLiteral(2)
+  WalkUpFromStmt UnaryOperator(-)
 WalkUpFromStmt IntegerLiteral(3)
 WalkUpFromStmt CompoundStmt
 )txt"));
@@ -675,7 +674,6 @@ WalkUpFromExpr IntegerLiteral(3)
   WalkUpFromStmt IntegerLiteral(3)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromUnaryMinus.
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
@@ -684,6 +682,9 @@ WalkUpFromExpr IntegerLiteral(1)
 TraverseUnaryMinus UnaryOperator(-)
   WalkUpFromExpr IntegerLiteral(2)
 WalkUpFromStmt IntegerLiteral(2)
+  WalkUpFromUnaryMinus UnaryOperator(-)
+WalkUpFromExpr UnaryOperator(-)
+  WalkUpFromStmt UnaryOperator(-)
 WalkUpFromExpr IntegerLiteral(3)
   WalkUpFromStmt IntegerLiteral(3)
 WalkUpFromStmt CompoundStmt
@@ -996,8 +997,6 @@ TraverseBinAdd BinaryOperator(+)
 WalkUpFromStmt IntegerLiteral(4)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromStmt for
-  // BinaryOperator(+).
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
@@ -1005,6 +1004,7 @@ WalkUpFromStmt IntegerLiteral(1)
 TraverseBinAdd BinaryOperator(+)
   WalkUpFromStmt IntegerLiteral(2)
   WalkUpFromStmt IntegerLiteral(3)
+  WalkUpFromStmt BinaryOperator(+)
 WalkUpFromStmt IntegerLiteral(4)
 WalkUpFromStmt CompoundStmt
 )txt"));
@@ -1067,7 +1067,6 @@ WalkUpFromExpr IntegerLiteral(4)
   WalkUpFromStmt IntegerLiteral(4)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromBinAdd.
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
@@ -1078,6 +1077,9 @@ TraverseBinAdd BinaryOperator(+)
 WalkUpFromStmt 

[clang] 7349479 - RecursiveASTVisitor: don't call WalkUp unnecessarily in post-order traversal

2020-07-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-06T13:38:01+02:00
New Revision: 7349479f2244c32c0184ca545af04adb171c8077

URL: 
https://github.com/llvm/llvm-project/commit/7349479f2244c32c0184ca545af04adb171c8077
DIFF: 
https://github.com/llvm/llvm-project/commit/7349479f2244c32c0184ca545af04adb171c8077.diff

LOG: RecursiveASTVisitor: don't call WalkUp unnecessarily in post-order 
traversal

Summary:
How does RecursiveASTVisitor call the WalkUp callback for expressions?

* In pre-order traversal mode, RecursiveASTVisitor calls the WalkUp
  callback from the default implementation of Traverse callbacks.

* In post-order traversal mode when we don't have a DataRecursionQueue,
  RecursiveASTVisitor also calls the WalkUp callback from the default
  implementation of Traverse callbacks.

* However, in post-order traversal mode when we have a DataRecursionQueue,
  RecursiveASTVisitor calls the WalkUp callback from PostVisitStmt.

As a result, when the user overrides the Traverse callback, in pre-order
traversal mode they never get the corresponding WalkUp callback. However
in the post-order traversal mode the WalkUp callback is invoked or not
depending on whether the data recursion optimization could be applied.

I had to adjust the implementation of TraverseCXXForRangeStmt in the
syntax tree builder to call the WalkUp method directly, as it was
relying on this behavior. There is an existing test for this
functionality and it prompted me to make this extra fix.

In addition, I had to fix the default implementation implementation of
RecursiveASTVisitor::TraverseSynOrSemInitListExpr to call WalkUpFrom in
the same manner as the implementation generated by the DEF_TRAVERSE_STMT
macro. Without this fix, the InitListExprIsPostOrderNoQueueVisitedTwice
test was failing because WalkUpFromInitListExpr was never called.

Reviewers: eduucaldas, ymandel

Reviewed By: eduucaldas, ymandel

Subscribers: gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82486

Added: 


Modified: 
clang/include/clang/AST/RecursiveASTVisitor.h
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index b16c1ae1e483..464a80d15cef 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -83,6 +83,42 @@ namespace clang {
   return false;
\
   } while (false)
 
+namespace detail {
+
+template 
+struct has_same_member_pointer_type : std::false_type {};
+template 
+struct has_same_member_pointer_type
+: std::true_type {};
+
+template  struct is_same_method_impl {
+  template 
+  static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+   SecondMethodPtrTy SecondMethodPtr) {
+return false;
+  }
+};
+
+template <> struct is_same_method_impl {
+  template 
+  static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+   SecondMethodPtrTy SecondMethodPtr) {
+return FirstMethodPtr == SecondMethodPtr;
+  }
+};
+
+/// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
+/// are pointers to the same non-static member function.
+template 
+bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+  SecondMethodPtrTy SecondMethodPtr) {
+  return is_same_method_impl::value>::isSameMethod(FirstMethodPtr, 
SecondMethodPtr);
+}
+
+} // end namespace detail
+
 /// A class that does preorder or postorder
 /// depth-first traversal on the entire Clang AST and visits each node.
 ///
@@ -325,23 +361,17 @@ template  class RecursiveASTVisitor {
   Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
 
 private:
-  template
-  struct has_same_member_pointer_type : std::false_type {};
-  template
-  struct has_same_member_pointer_type
-  : std::true_type {};
-
   // Traverse the given statement. If the most-derived traverse function takes 
a
   // data recursion queue, pass it on; otherwise, discard it. Note that the
   // first branch of this conditional must compile whether or not the derived
   // class can take a queue, so if we're taking the second arm, make the first
   // arm call our function rather than the derived class version.
 #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE)
\
-  (has_same_member_pointer_type::value 
\
+  (::clang::detail::has_same_member_pointer_type<  
\
+   decltype(::Traverse##NAME), 
\
+   decltype(::Traverse##NAME)>::value  
\
? static_cast::value,   
\
  Derived &, RecursiveASTVisitor &>>(*this) 
\
@@ -609,17 +639,38 @@ bool 

[clang] 5689b38 - Removed a RecursiveASTVisitor feature to visit operator kinds with different methods

2020-07-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-06T13:38:01+02:00
New Revision: 5689b38c6a4220cc5f6ba68a56486229b10071bf

URL: 
https://github.com/llvm/llvm-project/commit/5689b38c6a4220cc5f6ba68a56486229b10071bf
DIFF: 
https://github.com/llvm/llvm-project/commit/5689b38c6a4220cc5f6ba68a56486229b10071bf.diff

LOG: Removed a RecursiveASTVisitor feature to visit operator kinds with 
different methods

Summary:
This feature was only used in two places, but contributed a non-trivial
amount to the complexity of RecursiveASTVisitor, and was buggy (see my
recent patches where I was fixing the bugs that I noticed). I don't
think the convenience benefit of this feature is worth the complexity.

Besides complexity, another issue with the current state of
RecursiveASTVisitor is the non-uniformity in how it handles different
AST nodes. All AST nodes follow a regular pattern, but operators are
special -- and this special behavior not documented. Correct usage of
RecursiveASTVisitor relies on shadowing member functions with specific
names and signatures. Near misses don't cause any compile-time errors,
incorrectly named or typed methods are just silently ignored. Therefore,
predictability of RecursiveASTVisitor API is quite important.

This change reduces the size of the `clang` binary by 38 KB (0.2%) in
release mode, and by 7 MB (0.3%) in debug mode. The `clang-tidy` binary
is reduced by 205 KB (0.3%) in release mode, and by 5 MB (0.4%) in debug
mode. I don't think these code size improvements are significant enough
to justify this change on its own (for me, the primary motivation is
reducing code complexity), but they I think are a nice side-effect.

Reviewers: rsmith, sammccall, ymandel, aaron.ballman

Reviewed By: rsmith, sammccall, ymandel, aaron.ballman

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82921

Added: 


Modified: 
clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/RecursiveASTVisitor.h
clang/lib/ARCMigrate/TransProperties.cpp
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp 
b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
index 67f281b3ed1f..56d4cceb6002 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
@@ -500,7 +500,7 @@ void ForLoopIndexUseVisitor::addUsage(const Usage ) {
 /// int k = *i + 2;
 ///   }
 /// \endcode
-bool ForLoopIndexUseVisitor::TraverseUnaryDeref(UnaryOperator *Uop) {
+bool ForLoopIndexUseVisitor::TraverseUnaryOperator(UnaryOperator *Uop) {
   // If we dereference an iterator that's actually a pointer, count the
   // occurrence.
   if (isDereferenceOfUop(Uop, IndexVar)) {

diff  --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h 
b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
index b2cba8c0172a..4f75c9c7522f 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
@@ -346,7 +346,7 @@ class ForLoopIndexUseVisitor
   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
  Expr *Init);
   bool TraverseMemberExpr(MemberExpr *Member);
-  bool TraverseUnaryDeref(UnaryOperator *Uop);
+  bool TraverseUnaryOperator(UnaryOperator *Uop);
   bool VisitDeclRefExpr(DeclRefExpr *E);
   bool VisitDeclStmt(DeclStmt *S);
   bool TraverseStmt(Stmt *S);

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d0328b0ef54c..8a9a58aa01f8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -243,6 +243,34 @@ These are major API changes that have happened since the 
10.0.0 release of
 Clang. If upgrading an external codebase that uses Clang as a library,
 this section should help get you past the largest hurdles of upgrading.
 
+- ``RecursiveASTVisitor`` no longer calls separate methods to visit specific
+  operator kinds. Previously, ``RecursiveASTVisitor`` treated unary, binary,
+  and compound assignment operators as if they were subclasses of the
+  corresponding AST node. For example, the binary operator plus was treated as
+  if it was a ``BinAdd`` subclass of the ``BinaryOperator`` class: during AST
+  traversal of a ``BinaryOperator`` AST node that had a ``BO_Add`` opcode,
+  ``RecursiveASTVisitor`` was calling the ``TraverseBinAdd`` method instead of
+  ``TraverseBinaryOperator``. This feature was contributing a non-trivial
+  amount of complexity to the implementation of ``RecursiveASTVisitor``, it was
+  used only in a minor way in Clang, was not tested, and as a result it was
+  buggy. Furthermore, this feature was creating a 

[clang] c19c6b1 - Make RecursiveASTVisitor call WalkUpFrom for unary and binary operators in post-order traversal mode

2020-07-06 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-06T13:38:01+02:00
New Revision: c19c6b1722e5f71200c09cdb096245b98f03dce0

URL: 
https://github.com/llvm/llvm-project/commit/c19c6b1722e5f71200c09cdb096245b98f03dce0
DIFF: 
https://github.com/llvm/llvm-project/commit/c19c6b1722e5f71200c09cdb096245b98f03dce0.diff

LOG: Make RecursiveASTVisitor call WalkUpFrom for unary and binary operators in 
post-order traversal mode

Reviewers: ymandel, eduucaldas, rsmith

Reviewed By: eduucaldas, rsmith

Subscribers: gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82787

Added: 


Modified: 
clang/include/clang/AST/RecursiveASTVisitor.h
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index 464a80d15cef..9d93f1e99666 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -593,7 +593,6 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S,
 
   BINOP_LIST()
 #undef OPERATOR
-#undef BINOP_LIST
 
 #define OPERATOR(NAME) 
\
   case BO_##NAME##Assign:  
\
@@ -601,7 +600,6 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S,
 
   CAO_LIST()
 #undef OPERATOR
-#undef CAO_LIST
 }
   } else if (UnaryOperator *UnOp = dyn_cast(S)) {
 switch (UnOp->getOpcode()) {
@@ -611,7 +609,6 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S,
 
   UNARYOP_LIST()
 #undef OPERATOR
-#undef UNARYOP_LIST
 }
   }
 
@@ -633,27 +630,70 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt 
*S,
 
 template 
 bool RecursiveASTVisitor::PostVisitStmt(Stmt *S) {
+  // In pre-order traversal mode, each Traverse##STMT method is responsible for
+  // calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and
+  // does not call the default implementation, the WalkUpFrom callback is not
+  // called. Post-order traversal mode should provide the same behavior
+  // regarding method overrides.
+  //
+  // In post-order traversal mode the Traverse##STMT method, when it receives a
+  // DataRecursionQueue, can't call WalkUpFrom after traversing children 
because
+  // it only enqueues the children and does not traverse them. TraverseStmt
+  // traverses the enqueued children, and we call WalkUpFrom here.
+  //
+  // However, to make pre-order and post-order modes identical with regards to
+  // whether they call WalkUpFrom at all, we call WalkUpFrom if and only if the
+  // user did not override the Traverse##STMT method. We implement the override
+  // check with isSameMethod calls below.
+
+  if (BinaryOperator *BinOp = dyn_cast(S)) {
+switch (BinOp->getOpcode()) {
+#define OPERATOR(NAME) 
\
+  case BO_##NAME:  
\
+if (::clang::detail::isSameMethod(::TraverseBin##NAME, 
\
+  ::TraverseBin##NAME)) {  
\
+  TRY_TO(WalkUpFromBin##NAME(static_cast(S)));   
\
+}  
\
+return true;
+
+  BINOP_LIST()
+#undef OPERATOR
+
+#define OPERATOR(NAME) 
\
+  case BO_##NAME##Assign:  
\
+if (::clang::detail::isSameMethod( 
\
+::TraverseBin##NAME##Assign,   
\
+::TraverseBin##NAME##Assign)) {
\
+  TRY_TO(WalkUpFromBin##NAME##Assign(  
\
+  static_cast(S)));  
\
+}  
\
+return true;
+
+  CAO_LIST()
+#undef OPERATOR
+}
+  } else if (UnaryOperator *UnOp = dyn_cast(S)) {
+switch (UnOp->getOpcode()) {
+#define OPERATOR(NAME) 
\
+  case UO_##NAME:  
\
+if (::clang::detail::isSameMethod( 
\
+::TraverseUnary##NAME, 
\
+::TraverseUnary##NAME)) {  
\
+  TRY_TO(WalkUpFromUnary##NAME(static_cast(S)));  
\
+}  
\
+return true;
+
+  UNARYOP_LIST()
+#undef OPERATOR
+}
+  }
+
   switch (S->getStmtClass()) {
   case Stmt::NoStmtClass:
 break;
 #define ABSTRACT_STMT(STMT)
 #define STMT(CLASS, PARENT)
\
   case 

[clang] 19eaff6 - Revert RecursiveASTVisitor fixes.

2020-07-03 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-03T13:48:24+02:00
New Revision: 19eaff650c9c091e844f0a342540f1d10573772c

URL: 
https://github.com/llvm/llvm-project/commit/19eaff650c9c091e844f0a342540f1d10573772c
DIFF: 
https://github.com/llvm/llvm-project/commit/19eaff650c9c091e844f0a342540f1d10573772c.diff

LOG: Revert RecursiveASTVisitor fixes.

This reverts commit 8bf4c40af813e73de77739b33b8808f6bd13497b.
This reverts commit 7b0be962d681c408c8ecf7180c6ad8f9fbcdaf2d.
This reverts commit 94454442c3c15a67ae70ef3a73616632968973fc.

Some compilers on some buildbots didn't accept the specialization of
is_same_method_impl in a non-namespace scope.

Added: 


Modified: 
clang/include/clang/AST/RecursiveASTVisitor.h
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index ba36d5b23fc6..b16c1ae1e483 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -331,32 +331,6 @@ template  class RecursiveASTVisitor {
   struct has_same_member_pointer_type
   : std::true_type {};
 
-  template  struct is_same_method_impl {
-template 
-static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
- SecondMethodPtrTy SecondMethodPtr) {
-  return false;
-}
-  };
-
-  template <> struct is_same_method_impl {
-template 
-static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
- SecondMethodPtrTy SecondMethodPtr) {
-  return FirstMethodPtr == SecondMethodPtr;
-}
-  };
-
-  /// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
-  /// are pointers to the same non-static member function.
-  template 
-  bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
-SecondMethodPtrTy SecondMethodPtr) {
-return is_same_method_impl<
-has_same_member_pointer_type::
-value>::isSameMethod(FirstMethodPtr, SecondMethodPtr);
-  }
-
   // Traverse the given statement. If the most-derived traverse function takes 
a
   // data recursion queue, pass it on; otherwise, discard it. Note that the
   // first branch of this conditional must compile whether or not the derived
@@ -412,8 +386,6 @@ template  class RecursiveASTVisitor {
 if (!getDerived().shouldTraversePostOrder())   
\
   TRY_TO(WalkUpFromUnary##NAME(S));
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr());  
\
-if (!Queue && getDerived().shouldTraversePostOrder())  
\
-  TRY_TO(WalkUpFromUnary##NAME(S));
\
 return true;   
\
   }
\
   bool WalkUpFromUnary##NAME(UnaryOperator *S) {   
\
@@ -435,8 +407,6 @@ template  class RecursiveASTVisitor {
   TRY_TO(WalkUpFromBin##NAME(S));  
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS());  
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS());  
\
-if (!Queue && getDerived().shouldTraversePostOrder())  
\
-  TRY_TO(WalkUpFromBin##NAME(S));  
\
 return true;   
\
   }
\
   bool WalkUpFromBin##NAME(BINOP_TYPE *S) {
\
@@ -593,6 +563,7 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S,
 
   BINOP_LIST()
 #undef OPERATOR
+#undef BINOP_LIST
 
 #define OPERATOR(NAME) 
\
   case BO_##NAME##Assign:  
\
@@ -600,6 +571,7 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S,
 
   CAO_LIST()
 #undef OPERATOR
+#undef CAO_LIST
 }
   } else if (UnaryOperator *UnOp = dyn_cast(S)) {
 switch (UnOp->getOpcode()) {
@@ -609,6 +581,7 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S,
 
   UNARYOP_LIST()
 #undef OPERATOR
+#undef UNARYOP_LIST
 }
   }
 
@@ -630,84 +603,23 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt 
*S,
 
 template 
 bool RecursiveASTVisitor::PostVisitStmt(Stmt *S) {
-  // In pre-order traversal mode, each Traverse##STMT method is responsible for
-  // calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and
-  // does not call the default implementation, the WalkUpFrom callback is not
-  // called. Post-order traversal mode should provide the same behavior
-  // 

[clang] 9445444 - RecursiveASTVisitor: don't call WalkUp unnecessarily in post-order traversal

2020-07-03 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-03T13:03:19+02:00
New Revision: 94454442c3c15a67ae70ef3a73616632968973fc

URL: 
https://github.com/llvm/llvm-project/commit/94454442c3c15a67ae70ef3a73616632968973fc
DIFF: 
https://github.com/llvm/llvm-project/commit/94454442c3c15a67ae70ef3a73616632968973fc.diff

LOG: RecursiveASTVisitor: don't call WalkUp unnecessarily in post-order 
traversal

Summary:
How does RecursiveASTVisitor call the WalkUp callback for expressions?

* In pre-order traversal mode, RecursiveASTVisitor calls the WalkUp
  callback from the default implementation of Traverse callbacks.

* In post-order traversal mode when we don't have a DataRecursionQueue,
  RecursiveASTVisitor also calls the WalkUp callback from the default
  implementation of Traverse callbacks.

* However, in post-order traversal mode when we have a DataRecursionQueue,
  RecursiveASTVisitor calls the WalkUp callback from PostVisitStmt.

As a result, when the user overrides the Traverse callback, in pre-order
traversal mode they never get the corresponding WalkUp callback. However
in the post-order traversal mode the WalkUp callback is invoked or not
depending on whether the data recursion optimization could be applied.

I had to adjust the implementation of TraverseCXXForRangeStmt in the
syntax tree builder to call the WalkUp method directly, as it was
relying on this behavior. There is an existing test for this
functionality and it prompted me to make this extra fix.

In addition, I had to fix the default implementation implementation of
RecursiveASTVisitor::TraverseSynOrSemInitListExpr to call WalkUpFrom in
the same manner as the implementation generated by the DEF_TRAVERSE_STMT
macro. Without this fix, the InitListExprIsPostOrderNoQueueVisitedTwice
test was failing because WalkUpFromInitListExpr was never called.

Reviewers: eduucaldas, ymandel

Reviewed By: eduucaldas, ymandel

Subscribers: gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82486

Added: 


Modified: 
clang/include/clang/AST/RecursiveASTVisitor.h
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index b16c1ae1e483..821a6c549b71 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -331,6 +331,32 @@ template  class RecursiveASTVisitor {
   struct has_same_member_pointer_type
   : std::true_type {};
 
+  template  struct is_same_method_impl {
+template 
+static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+ SecondMethodPtrTy SecondMethodPtr) {
+  return false;
+}
+  };
+
+  template <> struct is_same_method_impl {
+template 
+static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+ SecondMethodPtrTy SecondMethodPtr) {
+  return FirstMethodPtr == SecondMethodPtr;
+}
+  };
+
+  /// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
+  /// are pointers to the same non-static member function.
+  template 
+  bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+SecondMethodPtrTy SecondMethodPtr) {
+return is_same_method_impl<
+has_same_member_pointer_type::
+value>::isSameMethod(FirstMethodPtr, SecondMethodPtr);
+  }
+
   // Traverse the given statement. If the most-derived traverse function takes 
a
   // data recursion queue, pass it on; otherwise, discard it. Note that the
   // first branch of this conditional must compile whether or not the derived
@@ -609,17 +635,38 @@ bool RecursiveASTVisitor::PostVisitStmt(Stmt *S) 
{
 #define ABSTRACT_STMT(STMT)
 #define STMT(CLASS, PARENT)
\
   case Stmt::CLASS##Class: 
\
-TRY_TO(WalkUpFrom##CLASS(static_cast(S))); break;
+/* In pre-order traversal mode, each Traverse##STMT method is responsible  
\
+ * for calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT 
\
+ * and does not call the default implementation, the WalkUpFrom callback   
\
+ * is not called. Post-order traversal mode should provide the same
\
+ * behavior regarding method overrides.
\
+ * 
\
+ * In post-order traversal mode the Traverse##STMT method, when it 
\
+ * receives a DataRecursionQueue, can't call WalkUpFrom after traversing   
\
+ * children because it only enqueues the children and does not traverse
\
+ * them. TraverseStmt traverses the enqueued children, and we call 
\
+ * WalkUpFrom here.   

[clang] 8bf4c40 - Make RecursiveASTVisitor call WalkUpFrom for operators when the data recursion queue is absent

2020-07-03 Thread Dmitri Gribenko via cfe-commits

Author: Dmitri Gribenko
Date: 2020-07-03T13:03:19+02:00
New Revision: 8bf4c40af813e73de77739b33b8808f6bd13497b

URL: 
https://github.com/llvm/llvm-project/commit/8bf4c40af813e73de77739b33b8808f6bd13497b
DIFF: 
https://github.com/llvm/llvm-project/commit/8bf4c40af813e73de77739b33b8808f6bd13497b.diff

LOG: Make RecursiveASTVisitor call WalkUpFrom for operators when the data 
recursion queue is absent

Reviewers: eduucaldas, ymandel, rsmith

Reviewed By: eduucaldas

Subscribers: gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82889

Added: 


Modified: 
clang/include/clang/AST/RecursiveASTVisitor.h
clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Removed: 




diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index 3d7cb73a471c..ba36d5b23fc6 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -412,6 +412,8 @@ template  class RecursiveASTVisitor {
 if (!getDerived().shouldTraversePostOrder())   
\
   TRY_TO(WalkUpFromUnary##NAME(S));
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr());  
\
+if (!Queue && getDerived().shouldTraversePostOrder())  
\
+  TRY_TO(WalkUpFromUnary##NAME(S));
\
 return true;   
\
   }
\
   bool WalkUpFromUnary##NAME(UnaryOperator *S) {   
\
@@ -433,6 +435,8 @@ template  class RecursiveASTVisitor {
   TRY_TO(WalkUpFromBin##NAME(S));  
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS());  
\
 TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS());  
\
+if (!Queue && getDerived().shouldTraversePostOrder())  
\
+  TRY_TO(WalkUpFromBin##NAME(S));  
\
 return true;   
\
   }
\
   bool WalkUpFromBin##NAME(BINOP_TYPE *S) {
\

diff  --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp 
b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
index 0a4e9aa1e9e8..70c7eb37ad4c 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
@@ -606,14 +606,13 @@ TraverseUnaryMinus UnaryOperator(-)
 WalkUpFromStmt IntegerLiteral(3)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromStmt for
-  // UnaryOperator(-).
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
 WalkUpFromStmt IntegerLiteral(1)
 TraverseUnaryMinus UnaryOperator(-)
   WalkUpFromStmt IntegerLiteral(2)
+  WalkUpFromStmt UnaryOperator(-)
 WalkUpFromStmt IntegerLiteral(3)
 WalkUpFromStmt CompoundStmt
 )txt"));
@@ -675,7 +674,6 @@ WalkUpFromExpr IntegerLiteral(3)
   WalkUpFromStmt IntegerLiteral(3)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromUnaryMinus.
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
@@ -684,6 +682,9 @@ WalkUpFromExpr IntegerLiteral(1)
 TraverseUnaryMinus UnaryOperator(-)
   WalkUpFromExpr IntegerLiteral(2)
 WalkUpFromStmt IntegerLiteral(2)
+  WalkUpFromUnaryMinus UnaryOperator(-)
+WalkUpFromExpr UnaryOperator(-)
+  WalkUpFromStmt UnaryOperator(-)
 WalkUpFromExpr IntegerLiteral(3)
   WalkUpFromStmt IntegerLiteral(3)
 WalkUpFromStmt CompoundStmt
@@ -996,8 +997,6 @@ TraverseBinAdd BinaryOperator(+)
 WalkUpFromStmt IntegerLiteral(4)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromStmt for
-  // BinaryOperator(+).
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
@@ -1005,6 +1004,7 @@ WalkUpFromStmt IntegerLiteral(1)
 TraverseBinAdd BinaryOperator(+)
   WalkUpFromStmt IntegerLiteral(2)
   WalkUpFromStmt IntegerLiteral(3)
+  WalkUpFromStmt BinaryOperator(+)
 WalkUpFromStmt IntegerLiteral(4)
 WalkUpFromStmt CompoundStmt
 )txt"));
@@ -1067,7 +1067,6 @@ WalkUpFromExpr IntegerLiteral(4)
   WalkUpFromStmt IntegerLiteral(4)
 )txt"));
 
-  // FIXME: The following log should include a call to WalkUpFromBinAdd.
   EXPECT_TRUE(visitorCallbackLogEqual(
   RecordingVisitor(ShouldTraversePostOrder::Yes), Code,
   R"txt(
@@ -1078,6 +1077,9 @@ TraverseBinAdd BinaryOperator(+)
 WalkUpFromStmt 

  1   2   3   >