llvm-project/clang/test/Analysis/misc-ps-eager-assume.m
Aaron Ballman 0f1c1be196 [clang] Remove rdar links; NFC
We have a new policy in place making links to private resources
something we try to avoid in source and test files. Normally, we'd
organically switch to the new policy rather than make a sweeping change
across a project. However, Clang is in a somewhat special circumstance
currently: recently, I've had several new contributors run into rdar
links around test code which their patch was changing the behavior of.
This turns out to be a surprisingly bad experience, especially for
newer folks, for a handful of reasons: not understanding what the link
is and feeling intimidated by it, wondering whether their changes are
actually breaking something important to a downstream in some way,
having to hunt down strangers not involved with the patch to impose on
them for help, accidental pressure from asking for potentially private
IP to be made public, etc. Because folks run into these links entirely
by chance (through fixing bugs or working on new features), there's not
really a set of problematic links to focus on -- all of the links have
basically the same potential for causing these problems. As a result,
this is an omnibus patch to remove all such links.

This was not a mechanical change; it was done by manually searching for
rdar, radar, radr, and other variants to find all the various
problematic links. From there, I tried to retain or reword the
surrounding comments so that we would lose as little context as
possible. However, because most links were just a plain link with no
supporting context, the majority of the changes are simple removals.

Differential Review: https://reviews.llvm.org/D158071
2023-08-28 12:13:42 -04:00

145 lines
5.3 KiB
Objective-C

// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify -fblocks %s
// expected-no-diagnostics
// Delta-reduced header stuff (needed for test cases).
typedef signed char BOOL;
typedef unsigned int NSUInteger;
typedef struct _NSZone NSZone;
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
@protocol NSObject - (BOOL)isEqual:(id)object;
- (oneway void)release;
@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone;
@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone;
@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
@end @interface NSObject <NSObject> {}
+ (id)alloc;
- (id)init;
@end typedef struct {}
NSFastEnumerationState;
@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
@end @interface NSMutableArray : NSArray - (void)addObject:(id)anObject;
- (BOOL)isEqualToString:(NSString *)aString;
@end @interface NSAutoreleasePool : NSObject {}
- (void)drain;
- (id)init;
@end
// This test case tests that (x != 0) is eagerly evaluated before stored to
// 'y'. This test case complements recoverCastedSymbol (see below) because
// the symbolic expression is stored to 'y' (which is a short instead of an
// int). recoverCastedSymbol() only recovers path-sensitivity when the
// symbolic expression is literally the branch condition.
//
void handle_assign_of_condition(int x) {
// The cast to 'short' causes us to lose symbolic constraint.
short y = (x != 0);
char *p = 0;
if (y) {
// This should be infeasible.
if (!(x != 0)) {
*p = 1; // no-warning
}
}
}
// In this test case, 'needsAnArray' is a signed char. The analyzer tracks
// a symbolic value for this variable, but in the branch condition it is
// promoted to 'int'. Currently the analyzer doesn't reason well about
// promotions of symbolic values, so this test case tests the logic in
// 'recoverCastedSymbol()' (ExprEngine.cpp) to test that we recover
// path-sensitivity and use the symbol for 'needsAnArray' in the branch
// condition.
//
void handle_symbolic_cast_in_condition(void) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"];
NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0;
if(needsAnArray)
[array release];
[pool drain];
}
// From PR 3836 (http://llvm.org/bugs/show_bug.cgi?id=3836)
//
// In this test case, the double '!' works fine with our symbolic constraints,
// but we don't support comparing SymConstraint != SymConstraint. By eagerly
// assuming the truth of !!a or !!b, we can compare these values directly.
//
void pr3836(int *a, int *b) {
if (!!a != !!b) /* one of them is NULL */
return;
if (!a && !b) /* both are NULL */
return;
*a = 1; // no-warning
*b = 1; // no-warning
}
//===---------------------------------------------------------------------===//
// This false positive occurred because the symbolic constraint on a short was
// not maintained via sign extension. The analyzer doesn't properly handle
// the sign extension, but now tracks the constraint. This particular
// case relies on -analyzer-options eagerly-assume=true because of the expression
// 'Flag1 != Count > 0'.
//===---------------------------------------------------------------------===//
void rdar7342806_aux(short x);
void rdar7342806(void) {
extern short Count;
extern short Flag1;
short *Pointer = 0;
short Flag2 = !!Pointer; // Flag2 is false (0).
short Ok = 1;
short Which;
if( Flag1 != Count > 0 )
// Static analyzer skips this so either
// Flag1 is true and Count > 0
// or
// Flag1 is false and Count <= 0
Ok = 0;
if( Flag1 != Flag2 )
// Analyzer skips this so Flag1 and Flag2 have the
// same value, both are false because Flag2 is false. And
// from that we know Count must be <= 0.
Ok = 0;
for( Which = 0;
Which < Count && Ok;
Which++ )
// This statement can only execute if Count > 0 which can only
// happen when Flag1 and Flag2 are both true and Flag2 will only
// be true when Pointer is not NULL.
rdar7342806_aux(*Pointer); // no-warning
}
//===---------------------------------------------------------------------===//
// PR 5627 - http://llvm.org/bugs/show_bug.cgi?id=5627
// This test case depends on using -analyzer-config eagerly-assume=true.
// The 'eagerly-assume=true' causes the path
// to bifurcate when evaluating the function call argument, and a state
// caching bug in ExprEngine::CheckerVisit (and friends) caused the store
// to 'p' to not be evaluated along one path, but then an autotransition caused
// the path to keep on propagating with 'p' still set to an undefined value.
// We would then get a bogus report of returning uninitialized memory.
// Note: CheckerVisit mistakenly cleared an existing node, and the cleared
// node was resurrected by GRStmtNodeBuilder::~GRStmtNodeBuilder(), where
// 'p' was not assigned.
//===---------------------------------------------------------------------===//
float *pr5627_f(int y);
float *pr5627_g(int x) {
float *p;
p = pr5627_f(!x);
return p; // no-warning
}