Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Malformed MC/DC Coverage record with macro definitions #77871

Closed
chapuni opened this issue Jan 12, 2024 · 7 comments · Fixed by #78969
Closed

Malformed MC/DC Coverage record with macro definitions #77871

chapuni opened this issue Jan 12, 2024 · 7 comments · Fixed by #78969

Comments

@chapuni
Copy link
Contributor

chapuni commented Jan 12, 2024

Clang -fcoverage-mcdc emits malformed records to crash llvm-cov with assert(NumConds == 0); if:

  1. At least two decisions (passes with one decision)
  2. Each expression has terms that come from macro definitions

Reproducible code (https://godbolt.org/z/xMGPafdvG)

#define D 1

extern void bar(void);

void foo(int a, int b) {
  if (a && D) bar();
  if (b && D) bar();
}

Unexpected Branch order will be seen.

  Decision,File 0, 6:7 -> 6:13 = M:0, C:2
  Branch,File 0, 6:7 -> 6:8 = #2, (#0 - #2) [1,2,0] 
  Expansion,File 0, 6:12 -> 6:13 = #2 (Expanded file = 1)
...
  Decision,File 0, 7:7 -> 7:13 = M:1, C:2
  Branch,File 0, 7:7 -> 7:8 = #5, (#0 - #5) [1,2,0] 
  Expansion,File 0, 7:12 -> 7:13 = #5 (Expanded file = 2)
...
  Branch,File 1, 1:11 -> 1:12 = 0, 0 [2,0,0] 
...
  Branch,File 2, 1:11 -> 1:12 = 0, 0 [2,0,0] 

("Decision, branch, branch, decision, branch, branch" is expected)

@chapuni
Copy link
Contributor Author

chapuni commented Jan 12, 2024

I think an easy workaround is to replace StartLoc for MC/DC branches and decisions (ID > 0).

@evodius96
Copy link
Contributor

I've got a fix for this; just testing it a bit more. I should have the PR hopefully tomorrow.

evodius96 added a commit to evodius96/llvm-project that referenced this issue Jan 20, 2024
…egion.

This fixes MC/DC issue llvm#77871 in which
branches under ExpansionRegions were not being included in the creation of the
MC/DC record. The fix is a slight refactor in how branches associated with an
MCDCDecisionRegion are gathered such that ExpansionRegions can be scanned
recursively.
chapuni added a commit to chapuni/llvm-project that referenced this issue Jan 22, 2024
evodius96 added a commit to evodius96/llvm-project that referenced this issue Jan 23, 2024
…egion.

This fixes MC/DC issue llvm#77871 in which
branches under ExpansionRegions were not being included in the creation of the
MC/DC record. The fix is a slight refactor in how branches associated with an
MCDCDecisionRegion are gathered such that ExpansionRegions can be scanned
recursively.
chapuni added a commit to chapuni/llvm-project that referenced this issue Jan 23, 2024
@MaskRay
Copy link
Member

MaskRay commented Jan 28, 2024

To summarize the problem:
-fcoverage-mcdc instrumentation emits Decision/Branch records.
The current llvm-cov implementation assumes that a MCDCDecisionRegion is followed by all its MCDCBranchRegion before another MCDCDecisionRegion is seen (assert(NumConds == 0)).
This breaks when a MCDCBranchRegion is inside a macro expansion (due to stable_sort mentioned later).

#78819 tries to scan forward to collect all MCDCBranchRegion for a MCDCDecisionRegion. The native implementation has an exponential time complexity.

#78969 tries to scan backward to find the associated MCDCDecisionRegion for a MCDCBranchRegion. The theoretical time complexity is quadratic, but it should be like linear in practice because logical operators in macros are presumably few.

I agree that #78969 is preferred.

Note: if we can avoid stable_sort in llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp and ensure that MCDCBranchRegion always immediately MCDCDecisionRegion, and change https://llvm.org/docs/CoverageMappingFormat.html#file-id-mapping not require the same FileID, the current llvm-cov implementation can be used again. But this may require require some code from the writer side.

@chapuni
Copy link
Contributor Author

chapuni commented Jan 28, 2024

Yet another interesting case (https://godbolt.org/z/hzeqoGcd8)

// The issue by RecursiveASTVisitor::TraverseParmVarDecl

#define BODY(code) { code; }

bool foo(int c) {
    BODY({
        if (c == '.' || c == '/') return true;
        if ('0' <= c && c <= '9') return true;
    });
    return false;
}
_Z3fooi:
  File 0, 5:17 -> 11:2 = #0
  Expansion,File 0, 6:5 -> 6:9 = #0 (Expanded file = 1)
  File 0, 6:9 -> 10:17 = ((#0 - #1) - #4)
  File 0, 6:9 -> 11:2 = (#0 - #1)
  File 1, 3:20 -> 3:29 = #0
  File 1, 3:22 -> 3:26 = #0
  File 1, 3:22 -> 3:26 = #2
  File 1, 3:22 -> 3:26 = #0
  File 1, 3:22 -> 3:26 = #1
  File 1, 3:22 -> 3:26 = (#0 - #1)
  File 1, 3:22 -> 3:26 = #5
  File 1, 3:22 -> 3:26 = (#0 - #1)
  File 1, 3:22 -> 3:26 = #4
  File 1, 3:22 -> 3:29 = (#0 - #1)
  Decision,File 1, 3:22 -> 3:26 = M:0, C:2
  Decision,File 1, 3:22 -> 3:26 = M:1, C:2
  Branch,File 1, 3:22 -> 3:26 = (#0 - #2), #2 [1,0,2] 
  Branch,File 1, 3:22 -> 3:26 = (#2 - #3), #3 [2,0,0] 
  Branch,File 1, 3:22 -> 3:26 = #5, ((#0 - #1) - #5) [1,2,0] 
  Branch,File 1, 3:22 -> 3:26 = #6, (#5 - #6) [2,0,0] 
  File 1, 3:26 -> 3:29 = ((#0 - #1) - #4)

@chapuni chapuni self-assigned this Jan 28, 2024
chapuni added a commit that referenced this issue Feb 2, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to #77871
chapuni added a commit that referenced this issue Feb 2, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes #77871

---------

Co-authored-by: Alan Phipps <[email protected]>
@chapuni
Copy link
Contributor Author

chapuni commented Feb 2, 2024

/cherry-pick 438fe1d d912f1f

@EugeneZelenko EugeneZelenko added this to the LLVM 18.X Release milestone Feb 3, 2024
@EugeneZelenko EugeneZelenko reopened this Feb 3, 2024
llvmbot pushed a commit to llvmbot/llvm-project that referenced this issue Feb 3, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871

(cherry picked from commit 438fe1d)
llvmbot pushed a commit to llvmbot/llvm-project that referenced this issue Feb 3, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
(cherry picked from commit d912f1f)
@llvmbot
Copy link
Collaborator

llvmbot commented Feb 3, 2024

/pull-request #80513

@tstellar
Copy link
Collaborator

tstellar commented Feb 3, 2024

The PR has been created so we will track status there.

@tstellar tstellar closed this as completed Feb 3, 2024
llvmbot pushed a commit to llvmbot/llvm-project that referenced this issue Feb 5, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871

(cherry picked from commit 438fe1d)
llvmbot pushed a commit to llvmbot/llvm-project that referenced this issue Feb 5, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
(cherry picked from commit d912f1f)
agozillon pushed a commit to agozillon/llvm-project that referenced this issue Feb 5, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871
agozillon pushed a commit to agozillon/llvm-project that referenced this issue Feb 5, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871

(cherry picked from commit 438fe1d)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
(cherry picked from commit d912f1f)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871

(cherry picked from commit 438fe1d)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
(cherry picked from commit d912f1f)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871

(cherry picked from commit 438fe1d)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
(cherry picked from commit d912f1f)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
To relax scanning record, tweak order by `Decision < Expansion`, or
`Expansion` could not be distinguished whether it belonged to `Decision`
or not.

Relevant to llvm#77871

(cherry picked from commit 438fe1d)
tstellar pushed a commit to tstellar/llvm-project that referenced this issue Feb 14, 2024
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes llvm#77871

---------

Co-authored-by: Alan Phipps <[email protected]>
(cherry picked from commit d912f1f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging a pull request may close this issue.

6 participants