Skip to content

Commit a446c9b

Browse files
authored
[clang][dataflow] Add support for CXXRewrittenBinaryOperator. (#81086)
This occurs in rewritten candidates for binary operators (a C++20 feature). The patch modifies UncheckedOptionalAccessModelTest to run in C++20 mode (as well as C++17 mode, as before) and to use rewritten candidates. The modified test fails without the newly added support for `CXXRewrittenBinaryOperator`.
1 parent 9ff3b82 commit a446c9b

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

clang/lib/Analysis/FlowSensitive/Transfer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,10 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
545545
VisitCallExpr(S);
546546
}
547547

548+
void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
549+
propagateValue(*RBO->getSemanticForm(), *RBO, Env);
550+
}
551+
548552
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
549553
if (S->getCastKind() == CK_ConstructorConversion) {
550554
const Expr *SubExpr = S->getSubExpr();

clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,17 @@ constexpr bool operator!=(const optional<T> &lhs, const optional<U> &rhs);
770770
771771
template <typename T>
772772
constexpr bool operator==(const optional<T> &opt, nullopt_t);
773+
774+
// C++20 and later do not define the following overloads because they are
775+
// provided by rewritten candidates instead.
776+
#if __cplusplus < 202002L
773777
template <typename T>
774778
constexpr bool operator==(nullopt_t, const optional<T> &opt);
775779
template <typename T>
776780
constexpr bool operator!=(const optional<T> &opt, nullopt_t);
777781
template <typename T>
778782
constexpr bool operator!=(nullopt_t, const optional<T> &opt);
783+
#endif // __cplusplus < 202002L
779784
780785
template <typename T, typename U>
781786
constexpr bool operator==(const optional<T> &opt, const U &value);
@@ -1289,6 +1294,15 @@ class UncheckedOptionalAccessTest
12891294
template <typename FuncDeclMatcher>
12901295
void ExpectDiagnosticsFor(std::string SourceCode,
12911296
FuncDeclMatcher FuncMatcher) {
1297+
// Run in C++17 and C++20 mode to cover differences in the AST between modes
1298+
// (e.g. C++20 can contain `CXXRewrittenBinaryOperator`).
1299+
for (const char *CxxMode : {"-std=c++17", "-std=c++20"})
1300+
ExpectDiagnosticsFor(SourceCode, FuncMatcher, CxxMode);
1301+
}
1302+
1303+
template <typename FuncDeclMatcher>
1304+
void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher FuncMatcher,
1305+
const char *CxxMode) {
12921306
ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
12931307
ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
12941308

@@ -1332,7 +1346,7 @@ class UncheckedOptionalAccessTest
13321346
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
13331347
})
13341348
.withASTBuildArgs(
1335-
{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"})
1349+
{"-fsyntax-only", CxxMode, "-Wno-undefined-inline"})
13361350
.withASTBuildVirtualMappedFiles(
13371351
tooling::FileContentMappings(Headers.begin(), Headers.end())),
13381352
/*VerifyResults=*/[&Diagnostics](

0 commit comments

Comments
 (0)