Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -3485,6 +3485,11 @@ static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; } bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); } + static bool isBitwiseOrShiftOp(Opcode Opc) { + return isBitwiseOp(Opc) || isShiftOp(Opc); + } + bool isBitwiseOrShiftOp() const { return isBitwiseOrShiftOp(getOpcode()); } + static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; } bool isRelationalOp() const { return isRelationalOp(getOpcode()); } Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def =================================================================== --- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -300,6 +300,14 @@ "Whether to place an event at each tracked condition.", false) +ANALYZER_OPTION(bool, CheckBitwise, "check-bitwise", + "Whether the bitwise (and shift) operations should be checked.", + false) + +//===----------------------------------------------------------------------===// +// Unsinged analyzer options. +//===----------------------------------------------------------------------===// + ANALYZER_OPTION(unsigned, CTUImportThreshold, "ctu-import-threshold", "The maximal amount of translation units that is considered " "for import when inlining functions during CTU analysis. " @@ -308,10 +316,6 @@ "various translation units.", 100u) -//===----------------------------------------------------------------------===// -// Unsinged analyzer options. -//===----------------------------------------------------------------------===// - ANALYZER_OPTION( unsigned, AlwaysInlineSize, "ipa-always-inline-size", "The size of the functions (in basic blocks), which should be considered " Index: clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -60,6 +60,11 @@ CheckerContext &Ctx) const { SVal X = Ctx.getSVal(Condition); if (X.isUndef()) { + if (const auto *BO = dyn_cast(Condition)) + if (BO->isBitwiseOrShiftOp() && + !Ctx.getAnalysisManager().getAnalyzerOptions().CheckBitwise) + return; + // Generate a sink node, which implicitly marks both outgoing branches as // infeasible. ExplodedNode *N = Ctx.generateErrorNode(); Index: clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -75,6 +75,9 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B, CheckerContext &C) const { if (C.getSVal(B).isUndef()) { + if (B->isBitwiseOrShiftOp() && + !C.getAnalysisManager().getAnalyzerOptions().CheckBitwise) + return; // Do not report assignments of uninitialized values inside swap functions. // This should allow to swap partially uninitialized structs Index: clang/test/Analysis/analyzer-config.c =================================================================== --- clang/test/Analysis/analyzer-config.c +++ clang/test/Analysis/analyzer-config.c @@ -25,6 +25,7 @@ // CHECK-NEXT: cfg-rich-constructors = true // CHECK-NEXT: cfg-scopes = false // CHECK-NEXT: cfg-temporary-dtors = true +// CHECK-NEXT: check-bitwise = false // CHECK-NEXT: cplusplus.Move:WarnOn = KnownsAndLocals // CHECK-NEXT: crosscheck-with-z3 = false // CHECK-NEXT: ctu-dir = "" @@ -93,4 +94,4 @@ // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 90 +// CHECK-NEXT: num-entries = 91 Index: clang/test/Analysis/bitwise-ops.c =================================================================== --- clang/test/Analysis/bitwise-ops.c +++ clang/test/Analysis/bitwise-ops.c @@ -1,4 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin13 \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -Wno-shift-count-overflow \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -verify %s void clang_analyzer_eval(int); #define CHECK(expr) if (!(expr)) return; clang_analyzer_eval(expr) Index: clang/test/Analysis/casts.c =================================================================== --- clang/test/Analysis/casts.c +++ clang/test/Analysis/casts.c @@ -1,7 +1,23 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -w %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 \ +// RUN: -analyzer-checker=core,alpha.core,debug.ExprInspection \ +// RUN: -analyzer-store=region \ +// RUN: -analyzer-config eagerly-assume=false \ +// RUN: -verify %s + +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 \ +// RUN: -analyzer-checker=core,alpha.core,debug.ExprInspection \ +// RUN: -analyzer-store=region \ +// RUN: -analyzer-config eagerly-assume=false %s \ +// RUN: -verify %s + +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 \ +// RUN: -analyzer-checker=core,alpha.core,debug.ExprInspection \ +// RUN: -DEAGERLY_ASSUME -w -verify %s + +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 \ +// RUN: -analyzer-checker=core,alpha.core,debug.ExprInspection \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -DEAGERLY_ASSUME -DBIT32 -w -verify %s extern void clang_analyzer_eval(_Bool); Index: clang/test/Analysis/diagnostics/track_subexpressions.cpp =================================================================== --- clang/test/Analysis/diagnostics/track_subexpressions.cpp +++ clang/test/Analysis/diagnostics/track_subexpressions.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -analyzer-output=text -verify %s typedef unsigned char uint8_t; @@ -38,7 +40,7 @@ for (int i = 0; i < 3; ++i) // expected-note@-1 3{{Loop condition is true. Entering loop body}} - // expected-note@-2 {{Loop condition is false. Execution continues on line 43}} + // expected-note@-2 {{Loop condition is false. Execution continues on line 45}} arr[i] = 0; int x = getInt(); int n = getIndex(x); // expected-note {{Calling 'getIndex'}} @@ -70,7 +72,7 @@ for (int i = 0; i < 3; ++i) // expected-note@-1 3{{Loop condition is true. Entering loop body}} - // expected-note@-2 {{Loop condition is false. Execution continues on line 75}} + // expected-note@-2 {{Loop condition is false. Execution continues on line 77}} arr[1][i] = 0; int x = getInt(); int n = getIndex(x); // expected-note {{Calling 'getIndex'}} Index: clang/test/Analysis/left-shift-cxx2a.cpp =================================================================== --- clang/test/Analysis/left-shift-cxx2a.cpp +++ clang/test/Analysis/left-shift-cxx2a.cpp @@ -1,5 +1,14 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify=expected,cxx17 -std=c++17 %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify=expected,cxx2a -std=c++2a %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin13 \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -Wno-shift-count-overflow \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -std=c++17 -verify=expected,cxx17 %s + +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin13 \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -Wno-shift-count-overflow \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -std=c++2a -verify=expected,cxx2a %s int testNegativeShift(int a) { if (a == -5) { Index: clang/test/Analysis/misc-ps-region-store.m =================================================================== --- clang/test/Analysis/misc-ps-region-store.m +++ clang/test/Analysis/misc-ps-region-store.m @@ -1,5 +1,22 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=alpha.core.CastToStruct \ +// RUN: -analyzer-checker=alpha.security.ReturnPtrRange \ +// RUN: -analyzer-checker=alpha.security.ArrayBound \ +// RUN: -analyzer-store=region \ +// RUN: -analyzer-opt-analyze-nested-blocks \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -Wno-objc-root-class -fblocks -verify %s + +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=alpha.core.CastToStruct \ +// RUN: -analyzer-checker=alpha.security.ReturnPtrRange \ +// RUN: -analyzer-checker=alpha.security.ArrayBound \ +// RUN: -analyzer-store=region \ +// RUN: -analyzer-opt-analyze-nested-blocks \ +// RUN: -analyzer-config check-bitwise=true \ +// RUN: -Wno-objc-root-class -fblocks -DTEST_64 -verify %s typedef long unsigned int size_t; void *memcpy(void *, const void *, size_t);