diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -975,6 +975,31 @@ /// Find a valid gap range between \p AfterLoc and \p BeforeLoc. Optional findGapAreaBetween(SourceLocation AfterLoc, SourceLocation BeforeLoc) { + size_t StartDepth = locationDepth(AfterLoc); + size_t EndDepth = locationDepth(BeforeLoc); + while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) { + bool UnnestStart = StartDepth >= EndDepth; + bool UnnestEnd = EndDepth >= StartDepth; + if (UnnestEnd) { + SourceLocation NestedLoc = getStartOfFileOrMacro(BeforeLoc); + assert(SM.isWrittenInSameFile(NestedLoc, BeforeLoc)); + + BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc); + assert(BeforeLoc.isValid()); + EndDepth--; + } + if (UnnestStart) { + SourceLocation NestedLoc = getEndOfFileOrMacro(AfterLoc); + assert(SM.isWrittenInSameFile(AfterLoc, NestedLoc)); + + AfterLoc = getIncludeOrExpansionLoc(AfterLoc); + assert(AfterLoc.isValid()); + AfterLoc = getPreciseTokenLocEnd(AfterLoc); + assert(AfterLoc.isValid()); + StartDepth--; + } + } + AfterLoc = getPreciseTokenLocEnd(AfterLoc); // If the start and end locations of the gap are both within the same macro // file, the range may not be in source order. if (AfterLoc.isMacroID() || BeforeLoc.isMacroID()) @@ -984,13 +1009,6 @@ return {{AfterLoc, BeforeLoc}}; } - /// Find the source range after \p AfterStmt and before \p BeforeStmt. - Optional findGapAreaBetween(const Stmt *AfterStmt, - const Stmt *BeforeStmt) { - return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)), - getStart(BeforeStmt)); - } - /// Emit a gap region between \p StartLoc and \p EndLoc with the given count. void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc, Counter Count) { @@ -1155,7 +1173,7 @@ adjustForOutOfOrderTraversal(getEnd(S)); // The body count applies to the area immediately after the increment. - auto Gap = findGapAreaBetween(S->getCond(), S->getBody()); + auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); @@ -1230,8 +1248,7 @@ } // The body count applies to the area immediately after the increment. - auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), - getStart(S->getBody())); + auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); @@ -1261,8 +1278,7 @@ BreakContinue BC = BreakContinueStack.pop_back_val(); // The body count applies to the area immediately after the range. - auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), - getStart(S->getBody())); + auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); @@ -1291,8 +1307,7 @@ BreakContinue BC = BreakContinueStack.pop_back_val(); // The body count applies to the area immediately after the collection. - auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), - getStart(S->getBody())); + auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); @@ -1411,7 +1426,7 @@ propagateCounts(ParentCount, S->getCond()); // The 'then' count applies to the area immediately after the condition. - auto Gap = findGapAreaBetween(S->getCond(), S->getThen()); + auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); @@ -1421,7 +1436,7 @@ Counter ElseCount = subtractCounters(ParentCount, ThenCount); if (const Stmt *Else = S->getElse()) { // The 'else' count applies to the area immediately after the 'then'. - Gap = findGapAreaBetween(S->getThen(), Else); + Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else)); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); extendRegion(Else); diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -6,7 +6,7 @@ // CHECK-NEXT: [[@LINE+3]]:12 -> [[@LINE+8]]:2 = #0 // CHECK-NEXT: [[@LINE+3]]:15 -> [[@LINE+3]]:19 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = 0, 0 -void foo() { // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:22 = #2 +void foo() { // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:22 = #2 if (int j = true ? nop() // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = #2 : nop(); // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = (#0 - #2) j) // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:8 = #0 @@ -41,13 +41,12 @@ // CHECK-NEXT: File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:13 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:13 = #5, (#0 - #5) - i = i == 0? // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+1]]:9 = #5 + i = i == 0? // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+1]]:9 = #5 i + 1 : // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:14 = #5 i + 2; // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:14 = (#0 - #5) - // CHECK-NEXT: File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:13 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:13 = #6, (#0 - #6) - // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:13 -> [[@LINE+2]]:14 = #6 + // CHECK-NEXT: File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:13 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:13 = #6, (#0 - #6) // CHECK-NEXT: File 0, [[@LINE+1]]:14 -> [[@LINE+1]]:20 = #6 i = i == 0?i + 12:i + 10; // CHECK-NEXT: File 0, [[@LINE]]:21 -> [[@LINE]]:27 = (#0 - #6) diff --git a/clang/test/CoverageMapping/macro-expressions.cpp b/clang/test/CoverageMapping/macro-expressions.cpp --- a/clang/test/CoverageMapping/macro-expressions.cpp +++ b/clang/test/CoverageMapping/macro-expressions.cpp @@ -53,38 +53,45 @@ // CHECK: foo // CHECK-NEXT: File 0, [[@LINE+1]]:17 -> {{[0-9]+}}:2 = #0 void foo(int i) { - // CHECK-NEXT: File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:8 = #0 - // CHECK: File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:12 = #1 + // CHECK-NEXT: File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:8 = #0 + // CHECK: Gap,File 0, [[@LINE+2]]:9 -> [[@LINE+2]]:10 = #1 + // CHECK-NEXT: File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:12 = #1 if (0) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:11 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:16 = #2 // CHECK-NEXT: File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:18 = #2 if (EXPR(i)) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:9 -> [[@LINE+2]]:14 = (#0 + #3) - // CHECK: File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:22 = #3 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:9 -> [[@LINE+3]]:14 = (#0 + #3) + // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:19 -> [[@LINE+2]]:20 = #3 + // CHECK-NEXT: File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:22 = #3 for (;NEXPR(i);) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:8 -> [[@LINE+4]]:14 = #0 - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:33 -> [[@LINE+3]]:35 = (#0 + #4) - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:43 -> [[@LINE+2]]:46 = #4 + // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:14 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:33 -> [[@LINE+4]]:35 = (#0 + #4) + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:43 -> [[@LINE+3]]:46 = #4 + // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:50 -> [[@LINE+2]]:51 = #4 // CHECK: File 0, [[@LINE+1]]:51 -> [[@LINE+1]]:53 = #4 for (ASSIGN(DECL(int, j), 0); LT(j, i); INC(j)) {} // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:9 = #0 ASSIGN(DECL(int, k), 0); - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:10 -> [[@LINE+3]]:12 = (#0 + #5) + // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:12 = (#0 + #5) + // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:19 -> [[@LINE+3]]:20 = #5 // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:31 = #5 // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:22 -> [[@LINE+1]]:25 = #5 while (LT(k, i)) { INC(k); } // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:8 = (#0 + #6) // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = (#0 + #6) do {} while (NEXPR(i)); - // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:8 -> [[@LINE+4]]:12 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:21 -> [[@LINE+3]]:22 = #7, #0 - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:26 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:12 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = #7, #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:23 -> [[@LINE+3]]:26 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:41 -> [[@LINE+2]]:42 = #7 // CHECK: File 0, [[@LINE+1]]:42 -> [[@LINE+1]]:44 = #7 for (DECL(int, j) : ARR(int, 1, 2, 3)) {} - // CHECK-NEXT: File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:10 -> [[@LINE+3]]:11 = #8, (#0 - #8) + // CHECK-NEXT: File 0, [[@LINE+5]]:10 -> [[@LINE+5]]:11 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #8, (#0 - #8) + // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #8 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #0 // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:23 -> [[@LINE+1]]:29 = #0 (void)(i ? PRIo64 : PRIu64); diff --git a/clang/test/CoverageMapping/macroparams2.c b/clang/test/CoverageMapping/macroparams2.c --- a/clang/test/CoverageMapping/macroparams2.c +++ b/clang/test/CoverageMapping/macroparams2.c @@ -6,11 +6,12 @@ int i, j; }; -// CHECK: File 0, [[@LINE+1]]:12 -> [[@LINE+10]]:2 = #0 +// CHECK: File 0, [[@LINE+1]]:12 -> [[@LINE+11]]:2 = #0 int main() { struct S arr[32] = { 0 }; int n = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:12 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:33 -> [[@LINE+2]]:34 = #1 // CHECK-NEXT: File 0, [[@LINE+1]]:34 -> [[@LINE+3]]:4 = #1 if (MACRO(arr[n].j, arr[n].i)) { n = 1; diff --git a/clang/test/CoverageMapping/macros.c b/clang/test/CoverageMapping/macros.c --- a/clang/test/CoverageMapping/macros.c +++ b/clang/test/CoverageMapping/macros.c @@ -38,37 +38,55 @@ // CHECK-NEXT: File 2, 4:17 -> 4:22 = #0 // CHECK-NEXT: func4 -void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+7]]:2 = #0 +void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+8]]:2 = #0 int i = 0; while (i++ < 10) // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:18 = (#0 + #1) - if (i < 5) // CHECK: File 0, [[@LINE]]:5 -> [[@LINE+3]]:14 = #1 + if (i < 5) // CHECK: File 0, [[@LINE]]:5 -> [[@LINE+4]]:14 = #1 // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1 // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:14 = #2, (#1 - #2) + // CHECK-NEXT: Gap,File 0, [[@LINE-3]]:15 -> [[@LINE+1]]:7 = #2 MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = #2 } // CHECK-NEXT: File 1, 4:17 -> 4:22 = #2 // CHECK-NOT: File 1 // CHECK-NEXT: func5 -void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+5]]:2 = #0 +void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0 int i = 0; if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:12 = #1, (#0 - #1) + // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:13 -> [[@LINE+1]]:5 = #1 MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1 } // CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #1 // CHECK-NEXT: func6 -void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+5]]:2 = #0 -begin: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+4]]:2 = #1 +void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+6]]:2 = #0 +begin: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+5]]:2 = #1 if (count--) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:16 = #1 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:16 = #2, (#1 - #2) + // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:17 -> [[@LINE+1]]:9 = #2 GOTO begin; // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:19 = #2 } // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2 // CHECK-NEXT: File 1, 7:14 -> 7:18 = #2 +// Regression test for gap region between macros. +// CHECK-NEXT: func7 +int k, l; +#define m(e) e##e +void func7() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0 + int kk,ll; // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:8 = #0 + if (k) // CHECK-NEXT: Branch,File 0, [[@LINE]]:7 -> [[@LINE]]:8 = #1 + m(k); // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE]]:5 = #1 + else // CHECK-NEXT: Expansion,File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:6 = #0 + l = m(l); // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:7 -> [[@LINE]]:5 = (#0 - #1) +} // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = (#0 - #1) + // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:10 = (#0 - #1) + // CHECK-NEXT: File 1, [[@LINE-9]]:14 -> [[@LINE-9]]:18 = #0 + // CHECK-NEXT: File 2, [[@LINE-10]]:14 -> [[@LINE-10]]:15 = (#0 - #1) + int main(int argc, const char *argv[]) { func(); func2(); diff --git a/clang/test/CoverageMapping/macroscopes.cpp b/clang/test/CoverageMapping/macroscopes.cpp --- a/clang/test/CoverageMapping/macroscopes.cpp +++ b/clang/test/CoverageMapping/macroscopes.cpp @@ -61,13 +61,15 @@ starts_a_scope ends_a_scope - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:17 -> [[@LINE+3]]:5 = #8 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:16 = #8 starts_a_while simple_stmt; x = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:3 -> [[@LINE+4]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:17 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+4]]:17 -> [[@LINE+4]]:18 = #9 // CHECK-NEXT: File 0, [[@LINE+3]]:18 -> [[@LINE+5]]:15 = #9 // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = #9 // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #9 diff --git a/clang/test/CoverageMapping/moremacros.c b/clang/test/CoverageMapping/moremacros.c --- a/clang/test/CoverageMapping/moremacros.c +++ b/clang/test/CoverageMapping/moremacros.c @@ -9,18 +9,20 @@ // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:12 = #0 if (!argc) {} // CHECK: File 0, [[@LINE]]:14 -> [[@LINE]]:16 = #1 - // CHECK-NEXT: File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #2, (#0 - #2) + // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #2, (#0 - #2) + // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #2 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #2 // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+4]]:8 = #2 if (!argc) LBRAC return 0; // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #2 - RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+7]]:3 = (#0 - #2) + RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+8]]:3 = (#0 - #2) - // CHECK-NEXT: File 0, [[@LINE+5]]:3 -> [[@LINE+16]]:2 = (#0 - #2) - // CHECK-NEXT: File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = (#0 - #2) - // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #3, ((#0 - #2) - #3) + // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+17]]:2 = (#0 - #2) + // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = (#0 - #2) + // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #3, ((#0 - #2) - #3) + // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #3 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #3 // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+3]]:4 = #3 if (!argc) LBRAC