return nullptr;
}
+static std::shared_ptr<PathDiagnosticEventPiece>
+constructDebugPieceForTrackedCondition(const Expr *Cond,
+ const ExplodedNode *N,
+ BugReporterContext &BRC) {
+
+ if (BRC.getAnalyzerOptions().AnalysisDiagOpt == PD_NONE ||
+ !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
+ return nullptr;
+
+ std::string ConditionText = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Cond->getSourceRange()),
+ BRC.getSourceManager(),
+ BRC.getASTContext().getLangOpts());
+
+ return std::make_shared<PathDiagnosticEventPiece>(
+ PathDiagnosticLocation::createBegin(
+ Cond, BRC.getSourceManager(), N->getLocationContext()),
+ (Twine() + "Tracking condition '" + ConditionText + "'").str());
+}
+
std::shared_ptr<PathDiagnosticPiece>
TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N,
BugReporterContext &BRC,
if (BR.addTrackedCondition(N)) {
bugreporter::trackExpressionValue(
N, Condition, BR, /*EnableNullFPSuppression=*/false);
+ return constructDebugPieceForTrackedCondition(Condition, N, BRC);
}
}
}
// RUN: -analyzer-config track-conditions=true \
// RUN: -analyzer-output=text \
// RUN: -analyzer-checker=core
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config track-conditions-debug=true \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-DEBUG
+
+// CHECK-INVALID-DEBUG: (frontend): invalid input for analyzer-config option
+// CHECK-INVALID-DEBUG-SAME: 'track-conditions-debug', that expects
+// CHECK-INVALID-DEBUG-SAME: 'track-conditions' to also be enabled
//
+// RUN: %clang_analyze_cc1 %s \
+// RUN: -verify=expected,tracking,debug \
+// RUN: -analyzer-config track-conditions=true \
+// RUN: -analyzer-config track-conditions-debug=true \
+// RUN: -analyzer-output=text \
+// RUN: -analyzer-checker=core
+
// RUN: %clang_analyze_cc1 %s -verify \
// RUN: -analyzer-output=text \
// RUN: -analyzer-checker=core
if (flag) // expected-note {{Assuming 'flag' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
+
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
if (flag) // expected-note {{Assuming 'flag' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
+
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
if (bar) // expected-note {{Assuming 'bar' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'bar'}}
if (flag) // expected-note {{Assuming 'flag' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
+
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
if (int flag = foo()) // tracking-note{{Calling 'foo'}}
// tracking-note@-1{{Returning from 'foo'}}
// tracking-note@-2{{'flag' initialized here}}
-
+ // debug-note@-3{{Tracking condition 'flag'}}
// expected-note@-4{{Assuming 'flag' is not equal to 0}}
// expected-note@-5{{Taking true branch}}
if (ConvertsToBool())
// tracking-note@-1 {{Calling 'ConvertsToBool::operator bool'}}
// tracking-note@-2{{Returning from 'ConvertsToBool::operator bool'}}
-
+ // debug-note@-3{{Tracking condition 'ConvertsToBool()'}}
// expected-note@-4{{Assuming the condition is true}}
// expected-note@-5{{Taking true branch}}
*x = 5; // expected-warning{{Dereference of null pointer}}
if (!flipCoin())
// tracking-note@-1{{Calling 'flipCoin'}}
// tracking-note@-2{{Returning from 'flipCoin'}}
- // expected-note@-3{{Assuming the condition is true}}
- // expected-note@-4{{Taking true branch}}
+ // debug-note@-3{{Tracking condition '!flipCoin()'}}
+ // expected-note@-4{{Assuming the condition is true}}
+ // expected-note@-5{{Taking true branch}}
*ptr = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
bool flipCoin() {
if (coin()) // tracking-note{{Assuming the condition is false}}
// tracking-note@-1{{Taking false branch}}
+ // debug-note@-2{{Tracking condition 'coin()'}}
return true;
return coin(); // tracking-note{{Returning value}}
}
if (!flipCoin())
// tracking-note@-1{{Calling 'flipCoin'}}
// tracking-note@-2{{Returning from 'flipCoin'}}
- // expected-note@-3{{Assuming the condition is true}}
- // expected-note@-4{{Taking true branch}}
+ // debug-note@-3{{Tracking condition '!flipCoin()'}}
+ // expected-note@-4{{Assuming the condition is true}}
+ // expected-note@-5{{Taking true branch}}
*ptr = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
if (flag) // expected-note{{Assuming 'flag' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
if (flag) // expected-note{{'flag' is 1}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
if (flag) // expected-note{{'flag' is 1}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
if (flag) // expected-note{{'flag' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}
if (flag) // expected-note{{'flag' is not equal to 0}}
// expected-note@-1{{Taking true branch}}
+ // debug-note@-2{{Tracking condition 'flag'}}
*x = 5; // expected-warning{{Dereference of null pointer}}
// expected-note@-1{{Dereference of null pointer}}
}