Counter TrueCount = getRegionCounter(E);
propagateCounts(ParentCount, E->getCond());
+ Counter OutCount;
if (!isa<BinaryConditionalOperator>(E)) {
// The 'then' count applies to the area immediately after the condition.
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
extendRegion(E->getTrueExpr());
- propagateCounts(TrueCount, E->getTrueExpr());
+ OutCount = propagateCounts(TrueCount, E->getTrueExpr());
}
extendRegion(E->getFalseExpr());
- propagateCounts(subtractCounters(ParentCount, TrueCount),
- E->getFalseExpr());
+ OutCount = addCounters(
+ OutCount, propagateCounts(subtractCounters(ParentCount, TrueCount),
+ E->getFalseExpr()));
+
+ if (OutCount != ParentCount) {
+ pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ }
// Create Branch Region around condition.
createBranchRegion(E->getCond(), TrueCount,
subtractCounters(RHSExecCnt, RHSTrueCnt));
}
+ // Determine whether the right side of OR operation need to be visited.
+ bool shouldVisitRHS(const Expr *LHS) {
+ bool LHSIsTrue = false;
+ bool LHSIsConst = false;
+ if (!LHS->isValueDependent())
+ LHSIsConst = LHS->EvaluateAsBooleanCondition(
+ LHSIsTrue, CVM.getCodeGenModule().getContext());
+ return !LHSIsConst || (LHSIsConst && !LHSIsTrue);
+ }
+
void VisitBinLOr(const BinaryOperator *E) {
extendRegion(E->getLHS());
- propagateCounts(getRegion().getCounter(), E->getLHS());
+ Counter OutCount = propagateCounts(getRegion().getCounter(), E->getLHS());
handleFileExit(getEnd(E->getLHS()));
// Counter tracks the right hand side of a logical or operator.
// Extract the RHS's "False" Instance Counter.
Counter RHSFalseCnt = getRegionCounter(E->getRHS());
+ if (!shouldVisitRHS(E->getLHS())) {
+ GapRegionCounter = OutCount;
+ }
+
// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();
included_func();
}
+// CHECK-LABEL: _Z7ornoretv:
+void abort() __attribute__((noreturn));
+
+int ornoret(void) {
+ ( true || (abort(), 0) ); // CHECK: Gap,File 0, [[@LINE]]:28 -> [[@LINE+1]]:3 = #0
+ ( false || (abort(), 0) ); // CHECK: Gap,File 0, [[@LINE]]:29 -> [[@LINE+1]]:3 = 0
+ return 0;
+}
+
+// CHECK-LABEL: _Z17abstractcondnoretv:
+int abstractcondnoret(void) {
+ ( true ? void (0) : abort() ); // CHECK: Gap,File 0, [[@LINE]]:33 -> [[@LINE+1]]:3 = #1
+ ( false ? void (0) : abort() ); // CHECK: Gap,File 0, [[@LINE]]:34 -> [[@LINE+1]]:3 = #2
+ ( true ? abort() : void (0) ); // CHECK: Gap,File 0, [[@LINE]]:33 -> [[@LINE+1]]:3 = (#2 - #3)
+ ( false ? abort() : void (0) ); // CHECK: Gap,File 0, [[@LINE]]:34 -> [[@LINE+1]]:3 = ((#2 - #3) - #4)
+ return 0;
+}
+
+// CHECK-LABEL: _Z13elsecondnoretv:
+int elsecondnoret(void) {
+ if (true) {} else {
+ true ? void (0) : abort();
+ } // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = (#1 + #2)
+ return 0;
+}
+
int main() {
foo(0);
foo(1);
while_loop();
gotos();
include();
+ ornoret();
+ abstractcondnoret();
+ elsecondnoret();
return 0;
}