1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CheckerRegistration.h"
10#include "clang/StaticAnalyzer/Core/Checker.h"
11#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
12#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
13#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
14#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
15#include "gtest/gtest.h"
16
17using namespace clang;
18using namespace ento;
19
20// Some dummy trait that we can mutate back and forth to force a new State.
21REGISTER_TRAIT_WITH_PROGRAMSTATE(Flag, bool)
22
23namespace {
24class FlipFlagOnCheckLocation : public Checker<check::Location> {
25public:
26 // We make sure we alter the State every time we model a checkLocation event.
27 void checkLocation(SVal l, bool isLoad, const Stmt *S,
28 CheckerContext &C) const {
29 ProgramStateRef State = C.getState();
30 State = State->set<Flag>(!State->get<Flag>());
31 C.addTransition(State);
32 }
33};
34
35void addFlagFlipperChecker(AnalysisASTConsumer &AnalysisConsumer,
36 AnalyzerOptions &AnOpts) {
37 AnOpts.CheckersAndPackages = {{"test.FlipFlagOnCheckLocation", true}};
38 AnalysisConsumer.AddCheckerRegistrationFn(Fn: [](CheckerRegistry &Registry) {
39 Registry.addChecker<FlipFlagOnCheckLocation>(FullName: "test.FlipFlagOnCheckLocation",
40 Desc: "Description", DocsUri: "");
41 });
42}
43
44TEST(ObjCTest, CheckLocationEventsShouldMaterializeInObjCForCollectionStmts) {
45 // Previously, the `ExprEngine::hasMoreIteration` may fired an assertion
46 // because we forgot to handle correctly the resulting nodes of the
47 // check::Location callback for the ObjCForCollectionStmts.
48 // This caused inconsistencies in the graph and triggering the assertion.
49 // See #124477 for more details.
50 std::string Diags;
51 EXPECT_TRUE(runCheckerOnCodeWithArgs<addFlagFlipperChecker>(
52 R"(
53 @class NSArray, NSDictionary, NSString;
54 extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
55 void entrypoint(NSArray *bowl) {
56 for (NSString *fruit in bowl) { // no-crash
57 NSLog(@"Fruit: %@", fruit);
58 }
59 })",
60 {"-x", "objective-c"}, Diags));
61}
62
63} // namespace
64

source code of clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp