From c7be2bea9b93c4b9043d83f223adbc16e0364fbe Mon Sep 17 00:00:00 2001 From: Csaba Dabis Date: Tue, 9 Jul 2019 23:47:09 +0000 Subject: [PATCH] Revert "[analyzer] CastValueChecker: Model casts" This reverts commit 27cf6664437efd640bb6db5594bafcce68fa2854. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@365584 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 17 +- .../Core/PathSensitive/CheckerContext.h | 11 - lib/StaticAnalyzer/Checkers/CMakeLists.txt | 1 - .../Checkers/CastValueChecker.cpp | 190 ------------------ test/Analysis/cast-value.cpp | 133 ------------ test/Analysis/return-value-guaranteed.cpp | 2 +- 6 files changed, 5 insertions(+), 349 deletions(-) delete mode 100644 lib/StaticAnalyzer/Checkers/CastValueChecker.cpp delete mode 100644 test/Analysis/cast-value.cpp diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 2b29efba66..95ea2d5234 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -100,7 +100,6 @@ def LLVMAlpha : Package<"llvm">, ParentPackage; // intended for API modeling that is not controlled by the target triple. def APIModeling : Package<"apiModeling">, Hidden; def GoogleAPIModeling : Package<"google">, ParentPackage, Hidden; -def LLVMAPIModeling : Package<"llvm">, ParentPackage, Hidden; def Debug : Package<"debug">, Hidden; @@ -275,6 +274,10 @@ def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">, let ParentPackage = APIModeling in { +def ReturnValueChecker : Checker<"ReturnValue">, + HelpText<"Model the guaranteed boolean return value of function calls">, + Documentation; + def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, HelpText<"Improve modeling of the C standard library functions">, Documentation; @@ -1106,18 +1109,6 @@ def LLVMConventionsChecker : Checker<"Conventions">, } // end "llvm" -let ParentPackage = LLVMAPIModeling in { - -def CastValueChecker : Checker<"CastValue">, - HelpText<"Model implementation of custom RTTIs">, - Documentation; - -def ReturnValueChecker : Checker<"ReturnValue">, - HelpText<"Model the guaranteed boolean return value of function calls">, - Documentation; - -} // end "apiModeling.llvm" - //===----------------------------------------------------------------------===// // Checkers modeling Google APIs. //===----------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 981133e669..0c68078bb3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -247,17 +247,6 @@ public: IsPrunable); } - /// A shorthand version of getNoteTag that accepts a plain note. - /// - /// @param Note The note. - /// @param IsPrunable Whether the note is prunable. It allows BugReporter - /// to omit the note from the report if it would make the displayed - /// bug path significantly shorter. - const NoteTag *getNoteTag(StringRef Note, bool IsPrunable = false) { - return getNoteTag( - [Note](BugReporterContext &, BugReport &) { return Note; }, IsPrunable); - } - /// Returns the word that should be used to refer to the declaration /// in the report. StringRef getDeclDescription(const Decl *D); diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 7cbd8c2a71..63ff770531 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -16,7 +16,6 @@ add_clang_library(clangStaticAnalyzerCheckers CallAndMessageChecker.cpp CastSizeChecker.cpp CastToStructChecker.cpp - CastValueChecker.cpp CheckObjCDealloc.cpp CheckObjCInstMethSignature.cpp CheckSecuritySyntaxOnly.cpp diff --git a/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp b/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp deleted file mode 100644 index ff5d12c27c..0000000000 --- a/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ /dev/null @@ -1,190 +0,0 @@ -//===- CastValueChecker - Model implementation of custom RTTIs --*- 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 defines CastValueChecker which models casts of custom RTTIs. -// -//===----------------------------------------------------------------------===// - -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "llvm/ADT/Optional.h" - -using namespace clang; -using namespace ento; - -namespace { -class CastValueChecker : public Checker { - using CastCheck = - std::function; - -public: - // We have three cases to evaluate a cast: - // 1) The parameter is non-null, the return value is non-null - // 2) The parameter is non-null, the return value is null - // 3) The parameter is null, the return value is null - // - // cast: 1; dyn_cast: 1, 2; cast_or_null: 1, 3; dyn_cast_or_null: 1, 2, 3. - bool evalCall(const CallEvent &Call, CheckerContext &C) const; - -private: - // These are known in the LLVM project. - const CallDescriptionMap CDM = { - {{{"llvm", "cast"}, 1}, &CastValueChecker::evalCast}, - {{{"llvm", "dyn_cast"}, 1}, &CastValueChecker::evalDynCast}, - {{{"llvm", "cast_or_null"}, 1}, &CastValueChecker::evalCastOrNull}, - {{{"llvm", "dyn_cast_or_null"}, 1}, - &CastValueChecker::evalDynCastOrNull}}; - - void evalCast(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const; - void evalDynCast(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const; - void evalCastOrNull(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const; - void evalDynCastOrNull(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const; -}; -} // namespace - -static std::string getCastName(const Expr *Cast) { - return Cast->getType()->getPointeeCXXRecordDecl()->getNameAsString(); -} - -static void evalNonNullParamNonNullReturn(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) { - ProgramStateRef State = C.getState()->assume(ParamDV, true); - if (!State) - return; - - State = State->BindExpr(CE, C.getLocationContext(), ParamDV, false); - - std::string CastFromName = getCastName(CE->getArg(0)); - std::string CastToName = getCastName(CE); - - const NoteTag *CastTag = C.getNoteTag( - [CastFromName, CastToName](BugReport &) -> std::string { - SmallString<128> Msg; - llvm::raw_svector_ostream Out(Msg); - - Out << "Assuming dynamic cast from '" << CastFromName << "' to '" - << CastToName << "' succeeds"; - return Out.str(); - }, - /*IsPrunable=*/true); - - C.addTransition(State, CastTag); -} - -static void evalNonNullParamNullReturn(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) { - ProgramStateRef State = C.getState()->assume(ParamDV, true); - if (!State) - return; - - State = State->BindExpr(CE, C.getLocationContext(), - C.getSValBuilder().makeNull(), false); - - std::string CastFromName = getCastName(CE->getArg(0)); - std::string CastToName = getCastName(CE); - - const NoteTag *CastTag = C.getNoteTag( - [CastFromName, CastToName](BugReport &) -> std::string { - SmallString<128> Msg; - llvm::raw_svector_ostream Out(Msg); - - Out << "Assuming dynamic cast from '" << CastFromName << "' to '" - << CastToName << "' fails"; - return Out.str(); - }, - /*IsPrunable=*/true); - - C.addTransition(State, CastTag); -} - -static void evalNullParamNullReturn(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) { - ProgramStateRef State = C.getState()->assume(ParamDV, false); - if (!State) - return; - - State = State->BindExpr(CE, C.getLocationContext(), - C.getSValBuilder().makeNull(), false); - - const NoteTag *CastTag = - C.getNoteTag("Assuming null pointer is passed into cast", - /*IsPrunable=*/true); - - C.addTransition(State, CastTag); -} - -void CastValueChecker::evalCast(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const { - evalNonNullParamNonNullReturn(CE, ParamDV, C); -} - -void CastValueChecker::evalDynCast(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const { - evalNonNullParamNonNullReturn(CE, ParamDV, C); - evalNonNullParamNullReturn(CE, ParamDV, C); -} - -void CastValueChecker::evalCastOrNull(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const { - evalNonNullParamNonNullReturn(CE, ParamDV, C); - evalNullParamNullReturn(CE, ParamDV, C); -} - -void CastValueChecker::evalDynCastOrNull(const CallExpr *CE, - DefinedOrUnknownSVal ParamDV, - CheckerContext &C) const { - evalNonNullParamNonNullReturn(CE, ParamDV, C); - evalNonNullParamNullReturn(CE, ParamDV, C); - evalNullParamNullReturn(CE, ParamDV, C); -} - -bool CastValueChecker::evalCall(const CallEvent &Call, - CheckerContext &C) const { - const CastCheck *Check = CDM.lookup(Call); - if (!Check) - return false; - - const auto *CE = cast(Call.getOriginExpr()); - if (!CE) - return false; - - // If we cannot obtain both of the classes we cannot be sure how to model it. - if (!CE->getType()->getPointeeCXXRecordDecl() || - !CE->getArg(0)->getType()->getPointeeCXXRecordDecl()) - return false; - - SVal ParamV = Call.getArgSVal(0); - auto ParamDV = ParamV.getAs(); - if (!ParamDV) - return false; - - (*Check)(this, CE, *ParamDV, C); - return true; -} - -void ento::registerCastValueChecker(CheckerManager &Mgr) { - Mgr.registerChecker(); -} - -bool ento::shouldRegisterCastValueChecker(const LangOptions &LO) { - return true; -} diff --git a/test/Analysis/cast-value.cpp b/test/Analysis/cast-value.cpp deleted file mode 100644 index fdf9aa22bf..0000000000 --- a/test/Analysis/cast-value.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// RUN: %clang_analyze_cc1 \ -// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\ -// RUN: -verify=logic %s -// RUN: %clang_analyze_cc1 \ -// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue \ -// RUN: -analyzer-output=text -verify %s - -void clang_analyzer_numTimesReached(); -void clang_analyzer_warnIfReached(); -void clang_analyzer_eval(bool); - -template -const X *cast(Y Value); - -template -const X *dyn_cast(Y Value); - -template -const X *cast_or_null(Y Value); - -template -const X *dyn_cast_or_null(Y Value); - -class Shape {}; -class Triangle : public Shape {}; -class Circle : public Shape {}; - -namespace test_cast { -void evalLogic(const Shape *S) { - const Circle *C = cast(S); - clang_analyzer_numTimesReached(); // logic-warning {{1}} - - if (S && C) - clang_analyzer_eval(C == S); // logic-warning {{TRUE}} - - if (S && !C) - clang_analyzer_warnIfReached(); // no-warning - - if (!S) - clang_analyzer_warnIfReached(); // no-warning -} -} // namespace test_cast - -namespace test_dyn_cast { -void evalLogic(const Shape *S) { - const Circle *C = dyn_cast(S); - clang_analyzer_numTimesReached(); // logic-warning {{2}} - - if (S && C) - clang_analyzer_eval(C == S); // logic-warning {{TRUE}} - - if (S && !C) - clang_analyzer_warnIfReached(); // logic-warning {{REACHABLE}} - - if (!S) - clang_analyzer_warnIfReached(); // no-warning -} -} // namespace test_dyn_cast - -namespace test_cast_or_null { -void evalLogic(const Shape *S) { - const Circle *C = cast_or_null(S); - clang_analyzer_numTimesReached(); // logic-warning {{2}} - - if (S && C) - clang_analyzer_eval(C == S); // logic-warning {{TRUE}} - - if (S && !C) - clang_analyzer_warnIfReached(); // no-warning - - if (!S) - clang_analyzer_eval(!C); // logic-warning {{TRUE}} -} -} // namespace test_cast_or_null - -namespace test_dyn_cast_or_null { -void evalLogic(const Shape *S) { - const Circle *C = dyn_cast_or_null(S); - clang_analyzer_numTimesReached(); // logic-warning {{3}} - - if (S && C) - clang_analyzer_eval(C == S); // logic-warning {{TRUE}} - - if (S && !C) - clang_analyzer_warnIfReached(); // logic-warning {{REACHABLE}} - - if (!S) - clang_analyzer_eval(!C); // logic-warning {{TRUE}} -} - -void evalNonNullParamNonNullReturn(const Shape *S) { - const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming dynamic cast from 'Shape' to 'Circle' succeeds}} - // expected-note@-2 {{Assuming pointer value is null}} - // expected-note@-3 {{'C' initialized here}} - - (void)(1 / !(bool)C); - // expected-note@-1 {{'C' is non-null}} - // expected-note@-2 {{Division by zero}} - // expected-warning@-3 {{Division by zero}} - // logic-warning@-4 {{Division by zero}} -} - -void evalNonNullParamNullReturn(const Shape *S) { - const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming dynamic cast from 'Shape' to 'Circle' fails}} - // expected-note@-2 {{Assuming pointer value is null}} - - if (const auto *T = dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming dynamic cast from 'Shape' to 'Triangle' succeeds}} - // expected-note@-2 {{'T' initialized here}} - // expected-note@-3 {{'T' is non-null}} - // expected-note@-4 {{Taking true branch}} - - (void)(1 / !T); - // expected-note@-1 {{'T' is non-null}} - // expected-note@-2 {{Division by zero}} - // expected-warning@-3 {{Division by zero}} - // logic-warning@-4 {{Division by zero}} - } -} - -void evalNullParamNullReturn(const Shape *S) { - const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming null pointer is passed into cast}} - // expected-note@-2 {{'C' initialized to a null pointer value}} - - (void)(1 / (bool)C); - // expected-note@-1 {{Division by zero}} - // expected-warning@-2 {{Division by zero}} - // logic-warning@-3 {{Division by zero}} -} -} // namespace test_dyn_cast_or_null diff --git a/test/Analysis/return-value-guaranteed.cpp b/test/Analysis/return-value-guaranteed.cpp index 367a8e5906..6461a98a7a 100644 --- a/test/Analysis/return-value-guaranteed.cpp +++ b/test/Analysis/return-value-guaranteed.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 \ -// RUN: -analyzer-checker=core,apiModeling.llvm.ReturnValue \ +// RUN: -analyzer-checker=core,apiModeling.ReturnValue \ // RUN: -analyzer-output=text -verify=class %s struct Foo { int Field; }; -- 2.40.0