64 lines · cpp
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-exception6//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([](CheckerRegistry &Registry) {39 Registry.addChecker<FlipFlagOnCheckLocation>("test.FlipFlagOnCheckLocation",40 "MockDescription");41 });42}43 44TEST(ObjCTest, CheckLocationEventsShouldMaterializeInObjCForCollectionStmts) {45 // Previously, the `ExprEngine::hasMoreIteration` may fired an assertion46 // because we forgot to handle correctly the resulting nodes of the47 // 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-crash57 NSLog(@"Fruit: %@", fruit);58 }59 })",60 {"-x", "objective-c"}, Diags));61}62 63} // namespace64