@@ -1282,28 +1282,35 @@ static raw_ostream &operator<<(raw_ostream &OS,
1282
1282
class UncheckedOptionalAccessTest
1283
1283
: public ::testing::TestWithParam<OptionalTypeIdentifier> {
1284
1284
protected:
1285
- void ExpectDiagnosticsFor (std::string SourceCode) {
1286
- ExpectDiagnosticsFor (SourceCode, ast_matchers::hasName (" target" ));
1285
+ void ExpectDiagnosticsFor (std::string SourceCode,
1286
+ bool IgnoreSmartPointerDereference = true ) {
1287
+ ExpectDiagnosticsFor (SourceCode, ast_matchers::hasName (" target" ),
1288
+ IgnoreSmartPointerDereference);
1287
1289
}
1288
1290
1289
- void ExpectDiagnosticsForLambda (std::string SourceCode) {
1291
+ void ExpectDiagnosticsForLambda (std::string SourceCode,
1292
+ bool IgnoreSmartPointerDereference = true ) {
1290
1293
ExpectDiagnosticsFor (
1291
- SourceCode, ast_matchers::hasDeclContext (
1292
- ast_matchers::cxxRecordDecl (ast_matchers::isLambda ())));
1294
+ SourceCode,
1295
+ ast_matchers::hasDeclContext (
1296
+ ast_matchers::cxxRecordDecl (ast_matchers::isLambda ())),
1297
+ IgnoreSmartPointerDereference);
1293
1298
}
1294
1299
1295
1300
template <typename FuncDeclMatcher>
1296
- void ExpectDiagnosticsFor (std::string SourceCode,
1297
- FuncDeclMatcher FuncMatcher ) {
1301
+ void ExpectDiagnosticsFor (std::string SourceCode, FuncDeclMatcher FuncMatcher,
1302
+ bool IgnoreSmartPointerDereference = true ) {
1298
1303
// Run in C++17 and C++20 mode to cover differences in the AST between modes
1299
1304
// (e.g. C++20 can contain `CXXRewrittenBinaryOperator`).
1300
1305
for (const char *CxxMode : {" -std=c++17" , " -std=c++20" })
1301
- ExpectDiagnosticsFor (SourceCode, FuncMatcher, CxxMode);
1306
+ ExpectDiagnosticsFor (SourceCode, FuncMatcher, CxxMode,
1307
+ IgnoreSmartPointerDereference);
1302
1308
}
1303
1309
1304
1310
template <typename FuncDeclMatcher>
1305
1311
void ExpectDiagnosticsFor (std::string SourceCode, FuncDeclMatcher FuncMatcher,
1306
- const char *CxxMode) {
1312
+ const char *CxxMode,
1313
+ bool IgnoreSmartPointerDereference) {
1307
1314
ReplaceAllOccurrences (SourceCode, " $ns" , GetParam ().NamespaceName );
1308
1315
ReplaceAllOccurrences (SourceCode, " $optional" , GetParam ().TypeName );
1309
1316
@@ -1328,8 +1335,7 @@ class UncheckedOptionalAccessTest
1328
1335
template <typename T>
1329
1336
T Make();
1330
1337
)" );
1331
- UncheckedOptionalAccessModelOptions Options{
1332
- /* IgnoreSmartPointerDereference=*/ true };
1338
+ UncheckedOptionalAccessModelOptions Options{IgnoreSmartPointerDereference};
1333
1339
std::vector<SourceLocation> Diagnostics;
1334
1340
llvm::Error Error = checkDataflow<UncheckedOptionalAccessModel>(
1335
1341
AnalysisInputs<UncheckedOptionalAccessModel>(
@@ -3721,6 +3727,50 @@ TEST_P(UncheckedOptionalAccessTest, ConstByValueAccessorWithModInBetween) {
3721
3727
)cc" );
3722
3728
}
3723
3729
3730
+ TEST_P (UncheckedOptionalAccessTest, ConstPointerAccessor) {
3731
+ ExpectDiagnosticsFor (R"cc(
3732
+ #include "unchecked_optional_access_test.h"
3733
+
3734
+ struct A {
3735
+ $ns::$optional<int> x;
3736
+ };
3737
+
3738
+ struct MyUniquePtr {
3739
+ A* operator->() const;
3740
+ };
3741
+
3742
+ void target(MyUniquePtr p) {
3743
+ if (p->x) {
3744
+ *p->x;
3745
+ }
3746
+ }
3747
+ )cc" ,
3748
+ /* IgnoreSmartPointerDereference=*/ false );
3749
+ }
3750
+
3751
+ TEST_P (UncheckedOptionalAccessTest, ConstPointerAccessorWithModInBetween) {
3752
+ ExpectDiagnosticsFor (R"cc(
3753
+ #include "unchecked_optional_access_test.h"
3754
+
3755
+ struct A {
3756
+ $ns::$optional<int> x;
3757
+ };
3758
+
3759
+ struct MyUniquePtr {
3760
+ A* operator->() const;
3761
+ void reset(A*);
3762
+ };
3763
+
3764
+ void target(MyUniquePtr p) {
3765
+ if (p->x) {
3766
+ p.reset(nullptr);
3767
+ *p->x; // [[unsafe]]
3768
+ }
3769
+ }
3770
+ )cc" ,
3771
+ /* IgnoreSmartPointerDereference=*/ false );
3772
+ }
3773
+
3724
3774
TEST_P (UncheckedOptionalAccessTest, ConstBoolAccessor) {
3725
3775
ExpectDiagnosticsFor (R"cc(
3726
3776
#include "unchecked_optional_access_test.h"
0 commit comments