[clang] [clang][test] Avoid writing to a potentially write-protected dir (PR #88258)
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
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
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)
@@ -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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
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
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
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
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]]`.
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
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().
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`
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
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
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
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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.
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()
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
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`
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
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
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
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()
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
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()
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`."
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`.
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
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
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`
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`
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.
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.
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`.
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.
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.
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`.
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.
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
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.
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
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
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
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.
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
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"".""
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"".
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"."
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`
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
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
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
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
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."
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
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.
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
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
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
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
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
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
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
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
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
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.
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
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
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