ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
#ifndef ANALYSIS_DIAGNOSTICS
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
#endif
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false)
-ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true)
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
#ifndef ANALYSIS_PURGE
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)
/// AnalysisDiagClients - Set of available diagnostic clients for rendering
/// analysis results.
enum AnalysisDiagClients {
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME,
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
#include "clang/StaticAnalyzer/Core/Analyses.def"
NUM_ANALYSIS_DIAG_CLIENTS
};
enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
- virtual bool supportsAllBlockEdges() const { return false; }
/// Return true if the PathDiagnosticConsumer supports individual
/// PathDiagnostics that span multiple files.
class PathDiagnosticConsumer;
typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
-#define CREATE_CONSUMER(NAME)\
-void create ## NAME ## DiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,\
- PathDiagnosticConsumers &C,\
- const std::string& prefix,\
- const Preprocessor &PP);
-
-CREATE_CONSUMER(HTML)
-CREATE_CONSUMER(Plist)
-CREATE_CONSUMER(PlistMultiFile)
-CREATE_CONSUMER(TextPath)
-
-#undef CREATE_CONSUMER
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
+void CREATEFN(AnalyzerOptions &AnalyzerOpts,\
+ PathDiagnosticConsumers &C,\
+ const std::string &Prefix,\
+ const Preprocessor &PP);
+#include "clang/StaticAnalyzer/Core/Analyses.def"
} // end 'ento' namespace
} // end 'clang' namespace
if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
StringRef Name = A->getValue();
AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
.Case(CMDFLAG, PD_##NAME)
#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NUM_ANALYSIS_DIAG_CLIENTS);
Store.cpp
SubEngine.cpp
SymbolManager.cpp
- TextPathDiagnostics.cpp
)
add_dependencies(clangStaticAnalyzerCore
PathGenerationScheme getGenerationScheme() const { return Extensive; }
bool supportsLogicalOpControlFlow() const { return true; }
- bool supportsAllBlockEdges() const { return true; }
virtual bool supportsCrossFileDiagnostics() const {
return SupportsCrossFileDiagnostics;
}
+++ /dev/null
-//===--- TextPathDiagnostics.cpp - Text Diagnostics for Paths ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the TextPathDiagnostics object.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace clang;
-using namespace ento;
-using namespace llvm;
-
-namespace {
-
-/// \brief Simple path diagnostic client used for outputting as diagnostic notes
-/// the sequence of events.
-class TextPathDiagnostics : public PathDiagnosticConsumer {
- const std::string OutputFile;
- DiagnosticsEngine &Diag;
-
-public:
- TextPathDiagnostics(const std::string& output, DiagnosticsEngine &diag)
- : OutputFile(output), Diag(diag) {}
-
- void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- FilesMade *filesMade);
-
- virtual StringRef getName() const {
- return "TextPathDiagnostics";
- }
-
- PathGenerationScheme getGenerationScheme() const { return Minimal; }
- bool supportsLogicalOpControlFlow() const { return true; }
- bool supportsAllBlockEdges() const { return true; }
- virtual bool supportsCrossFileDiagnostics() const { return true; }
-};
-
-} // end anonymous namespace
-
-void ento::createTextPathDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
- PathDiagnosticConsumers &C,
- const std::string& out,
- const Preprocessor &PP) {
- C.push_back(new TextPathDiagnostics(out, PP.getDiagnostics()));
-}
-
-void TextPathDiagnostics::FlushDiagnosticsImpl(
- std::vector<const PathDiagnostic *> &Diags,
- FilesMade *) {
- for (std::vector<const PathDiagnostic *>::iterator it = Diags.begin(),
- et = Diags.end(); it != et; ++it) {
- const PathDiagnostic *D = *it;
-
- PathPieces FlatPath = D->path.flatten(/*ShouldFlattenMacros=*/true);
- for (PathPieces::const_iterator I = FlatPath.begin(), E = FlatPath.end();
- I != E; ++I) {
- unsigned diagID =
- Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Note,
- (*I)->getString());
- Diag.Report((*I)->getLocation().asLocation(), diagID);
- }
- }
-}
// Special PathDiagnosticConsumers.
//===----------------------------------------------------------------------===//
-static void createPlistHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
- PathDiagnosticConsumers &C,
- const std::string &prefix,
- const Preprocessor &PP) {
+void ento::createPlistHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+ PathDiagnosticConsumers &C,
+ const std::string &prefix,
+ const Preprocessor &PP) {
createHTMLDiagnosticConsumer(AnalyzerOpts, C,
llvm::sys::path::parent_path(prefix), PP);
createPlistDiagnosticConsumer(AnalyzerOpts, C, prefix, PP);
}
+void ento::createTextPathDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+ PathDiagnosticConsumers &C,
+ const std::string &Prefix,
+ const clang::Preprocessor &PP) {
+ llvm_unreachable("'text' consumer should be enabled on ClangDiags");
+}
+
namespace {
class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
DiagnosticsEngine &Diag;
+ bool IncludePath;
public:
- ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag) : Diag(Diag) {}
+ ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
+ : Diag(Diag), IncludePath(false) {}
virtual ~ClangDiagPathDiagConsumer() {}
virtual StringRef getName() const { return "ClangDiags"; }
- virtual PathGenerationScheme getGenerationScheme() const { return None; }
+
+ virtual bool supportsLogicalOpControlFlow() const { return true; }
+ virtual bool supportsCrossFileDiagnostics() const { return true; }
+
+ virtual PathGenerationScheme getGenerationScheme() const {
+ return IncludePath ? Minimal : None;
+ }
+
+ void enablePaths() {
+ IncludePath = true;
+ }
+
+ void emitDiag(SourceLocation L, unsigned DiagID,
+ ArrayRef<SourceRange> Ranges) {
+ DiagnosticBuilder DiagBuilder = Diag.Report(L, DiagID);
+
+ for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
+ I != E; ++I) {
+ DiagBuilder << *I;
+ }
+ }
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) {
unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning,
TmpStr);
SourceLocation L = PD->getLocation().asLocation();
- DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
+ emitDiag(L, ErrorDiag, PD->path.back()->getRanges());
+
+ if (!IncludePath)
+ continue;
- // Get the ranges from the last point in the path.
- ArrayRef<SourceRange> Ranges = PD->path.back()->getRanges();
+ PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);
+ for (PathPieces::const_iterator PI = FlatPath.begin(),
+ PE = FlatPath.end();
+ PI != PE; ++PI) {
+ unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note,
+ (*PI)->getString());
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- diagBuilder << *I;
+ SourceLocation NoteLoc = (*PI)->getLocation().asLocation();
+ emitDiag(NoteLoc, NoteID, (*PI)->getRanges());
}
}
}
void DigestAnalyzerOptions() {
// Create the PathDiagnosticConsumer.
- PathConsumers.push_back(new ClangDiagPathDiagConsumer(PP.getDiagnostics()));
+ ClangDiagPathDiagConsumer *clangDiags =
+ new ClangDiagPathDiagConsumer(PP.getDiagnostics());
+ PathConsumers.push_back(clangDiags);
+
+ if (Opts->AnalysisDiagOpt == PD_TEXT) {
+ clangDiags->enablePaths();
- if (!OutDir.empty()) {
+ } else if (!OutDir.empty()) {
switch (Opts->AnalysisDiagOpt) {
default:
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
case PD_##NAME: CREATEFN(*Opts.getPtr(), PathConsumers, OutDir, PP);\
break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
}
- } else if (Opts->AnalysisDiagOpt == PD_TEXT) {
- // Create the text client even without a specified output file since
- // it just uses diagnostic notes.
- createTextPathDiagnosticConsumer(*Opts.getPtr(), PathConsumers, "", PP);
}
// Create the analyzer component creators.
--- /dev/null
+// RUN: %clang --analyze -Xanalyzer -analyzer-output=text -fno-caret-diagnostics %s 2>&1 | FileCheck %s
+
+void testA() {
+ int *p = 0;
+ *p = 1;
+
+ // CHECK-LABEL: text-diagnostics.c:{{.*}}:6: warning: Dereference of null pointer (loaded from variable 'p')
+ // CHECK-NEXT: text-diagnostics.c:[[@LINE-4]]:3: note: 'p' initialized to a null pointer value
+ // CHECK-NEXT: text-diagnostics.c:[[@LINE-4]]:6: note: Dereference of null pointer (loaded from variable 'p')
+}
+
+void testB(int *q) {
+ if (q)
+ return;
+ *q = 1;
+
+ // CHECK-LABEL: text-diagnostics.c:{{.*}}:6: warning: Dereference of null pointer (loaded from variable 'q')
+ // CHECK-NEXT: text-diagnostics.c:[[@LINE-5]]:7: note: Assuming 'q' is null
+ // CHECK-NEXT: text-diagnostics.c:[[@LINE-6]]:3: note: Taking false branch
+ // CHECK-NEXT: text-diagnostics.c:[[@LINE-5]]:6: note: Dereference of null pointer (loaded from variable 'q')
+}
void creationViaCFCreate () {
- CFTypeRef leaked = CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void makeCollectable () {
- CFTypeRef leaked = CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
CFMakeCollectable(leaked); // expected-note{{In GC mode a call to 'CFMakeCollectable' decrements an object's retain count and registers the object with the garbage collector. An object must have a 0 retain count to be garbage collected. After this call its retain count is +1}}
NSMakeCollectable(leaked); // expected-note{{In GC mode a call to 'NSMakeCollectable' decrements an object's retain count and registers the object with the garbage collector. Since it now has a 0 retain count the object can be automatically collected by the garbage collector}}
CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +1 retain count. The object is not eligible for garbage collection until the retain count reaches 0 again}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void retainReleaseIgnored () {
@implementation Foo (FundamentalRuleUnderGC)
- (id)getViolation {
- id object = (id) CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- return object; // expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'getViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
+ id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'getViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
}
- (id)copyViolation {
- id object = (id) CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- return object; // expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'copyViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
+ id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'copyViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
}
@end
void creationViaAlloc () {
- id leaked = [[NSObject alloc] init]; // expected-warning{{leak}} expected-note{{Method returns an Objective-C object with a +1 retain count}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ id leaked = [[NSObject alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void creationViaCFCreate () {
- CFTypeRef leaked = CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void acquisitionViaMethod (Foo *foo) {
- id leaked = [foo methodWithValue]; // expected-warning{{leak}} expected-note{{Method returns an Objective-C object with a +0 retain count}}
+ id leaked = [foo methodWithValue]; // expected-note{{Method returns an Objective-C object with a +0 retain count}}
[leaked retain]; // expected-note{{Reference count incremented. The object now has a +1 retain count}}
[leaked retain]; // expected-note{{Reference count incremented. The object now has a +2 retain count}}
[leaked release]; // expected-note{{Reference count decremented. The object now has a +1 retain count}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void acquisitionViaProperty (Foo *foo) {
- id leaked = foo.propertyValue; // expected-warning{{leak}} expected-note{{Property returns an Objective-C object with a +0 retain count}}
+ id leaked = foo.propertyValue; // expected-note{{Property returns an Objective-C object with a +0 retain count}}
[leaked retain]; // expected-note{{Reference count incremented. The object now has a +1 retain count}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void acquisitionViaCFFunction () {
- CFTypeRef leaked = CFGetSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object with a +0 retain count}}
+ CFTypeRef leaked = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object with a +0 retain count}}
CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +1 retain count}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void explicitDealloc () {
}
void makeCollectableIgnored () {
- CFTypeRef leaked = CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
CFMakeCollectable(leaked); // expected-note{{When GC is not enabled a call to 'CFMakeCollectable' has no effect on its argument}}
NSMakeCollectable(leaked); // expected-note{{When GC is not enabled a call to 'NSMakeCollectable' has no effect on its argument}}
- return; // expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
CFTypeRef CFCopyRuleViolation () {
}
CFTypeRef CFGetRuleViolation () {
- CFTypeRef object = CFCreateSomething(); // expected-warning{{leak}} expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
- return object; // expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'. This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
+ CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'. This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
}
@implementation Foo (FundamentalMemoryManagementRules)
}
- (id)getViolation {
- id result = [[Foo alloc] init]; // expected-warning{{leak}} expected-note{{Method returns an Objective-C object with a +1 retain count}}
- return result; // expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'. This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
+ id result = [[Foo alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ return result; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'. This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
}
- (id)copyAutorelease {
// expected-note@-3 {{Returning from 'initX'}}
// expected-note@-4 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}}
// initI is inlined because the allocation happens within initY
- id y = [[MyObj alloc] initY]; // expected-warning {{Potential leak of an object}}
+ id y = [[MyObj alloc] initY];
// expected-note@-1 {{Calling 'initY'}}
// expected-note@-2 {{Returning from 'initY'}}
// initZ is not inlined
- id z = [[MyObj alloc] initZ];
+ id z = [[MyObj alloc] initZ]; // expected-warning {{Potential leak of an object}}
// expected-note@-1 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}}
[x release];