[clang] [Clang] Fix inverted diagnostic location for duplicate default labels (PR #180447)

Youssed Mohamed Abdul-Sataar via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 10 09:25:40 PST 2026


youssef47048 wrote:

After doing more investigation. I found that the inconsistency comes from how the AST is built for the standard switch case and the nested switch case.

- In standard switch case like https://godbolt.org/z/d9ef7b6hj

When parsing, it applies the LIFO, which means the `TheDefaultStmt`  takes the second default, and the DS takes the first default. this cause the error to be pointing to the first default. **[the BUG]**

- In nested switch case, the parser finishes the **Inner** statement before the **Outer** one. Because of how they are added to the list, they end up in Correct Textual Order in the AST list.

 
Note how the error is reported on the bottom line. (Correct). https://godbolt.org/z/oM5qhxYE8


Also, when I swapped the DS and TheDefaultStmt
```

 Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined);
 Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev);
```

to

```
 Diag(TheDefaultStmt->getDefaultLoc(), diag::err_multiple_default_labels_defined);
 Diag(DS->getDefaultLoc(), diag::note_duplicate_case_prev);
```
The error is fixed and it points the error to the last default in the **standard switch case**

but this work for this test case **the standard switch**:

```
void test5(int z) { 
  switch(z) {
    default: break; // expected-note {{previous case defined here}}
    case 1: break;
    default:  // expected-error {{multiple default labels in one switch}}
      break;
  }
} 

```

but fails for the **nested switch case**

```
void test5(int z) { 
  switch(z) {
    default:// expected-note {{previous case defined here}}
    case 1: 
    default:  // expected-error {{multiple default labels in one switch}}
      break;
  }
} 
```

Finally I found this comment in the code base

```
        // FIXME: Remove the default statement from the switch block so that
        // we'll return a valid AST.  This requires recursing down the AST and
        // finding it, not something we are set up to do right now.  For now,
        // just lop the entire switch stmt out of the AST.
```


> Also, I apologyize for mentionting that there 
> is inconsistent between language modes:
> 
> In C: The list iterates forward.
> In C++: The list iterates in reverse order.

https://github.com/llvm/llvm-project/pull/180447


More information about the cfe-commits mailing list