<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/101764>101764</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            `DeclRefExpr::getEndLoc()` returns the same `SourceLocation` as `DeclRefExpr::getStartLoc()` 
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            bug,
            clang:diagnostics
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          delcypher
      </td>
    </tr>
</table>

<pre>
    **Problem**

`DeclRefExpr::getEndLoc()` returns the same `SourceLocation` as `DeclRefExpr::getStartLoc()`. This means calling `DeclRefExpr::getSourceRange()` doesn't return a useful range for diagnostic emission.

I would have expected `DeclRefExpr::getEndLoc()` to return a SourceLocation that points to the last character of the identifier in the source code.

**Cause**

Calling `DeclRefExpr::getSourceRange()` on a `DeclRefExpr` effectively returns a 1 character range because it uses

```
  /// This implementation is used when a class doesn't provide a custom
  /// implementation of getSourceRange.  Overload resolution should pick it over
  /// the implementation above because it's more specialized according to
  /// function template partial ordering.
  template <class S>
  SourceRange getSourceRangeImpl(const Stmt *stmt,
 SourceRange (Stmt::*v)() const) {
    return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(),
                       static_cast<const S *>(stmt)->getEndLoc());
  }
```

and `DeclRefExpr::getEndLoc()` is implemented as

```
SourceLocation DeclRefExpr::getEndLoc() const {
  if (hasExplicitTemplateArgs())
    return getRAngleLoc();
 return getNameInfo().getEndLoc();
}
```

This effectively returns `DeclRefExpr::getLocation()` when `DeclarationNameInfo::Name.getNameKind()` is `DeclarationName::Identifier` because of ...

```
 DeclarationNameInfo getNameInfo() const {
    return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc);
 }

  SourceLocation getLocation() const { return DeclRefExprBits.Loc; }
```

`DeclRefExpr::getLocation()` effectively returns the same location as `DeclRefExpr::getStartLoc()`.

**Fixing**

We might be able to fix this by doing something like...

```
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index a3ac5551e0cc..4544c28c59db 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -497,7 +497,9 @@ void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) cons
 
 SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
   switch (Name.getNameKind()) {
-  case DeclarationName::Identifier:
+  case DeclarationName::Identifier: {
+ return NameLoc.getLocWithOffset(Name.getAsIdentifierInfo()->getLength());
+ }
   case DeclarationName::CXXDeductionGuideName:
     return NameLoc;
 
```

Not sure if this really works in the presence of macros.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEV0tv2zoT_TX0ZmBBpmQ7XnhhJ_GH4AvaoCnQ7gqKGkm8pUiBpJzk_voLStbDrzS5mxsY8YPzODxzZkgxa0WuENdkviXzuwmrXaHNOkXJ36oCzSTR6dua0A2hmyejE4ll-4WEdyTs_i_CO-TyG2b3r5Uh0YZEmxzdvUofNSf0htAVWYRg0NVGWXAFgmUlAlmEz7o2HB81Z05o5a2YhSvxnh0zbhwxgO-FsFAiUxY4k1Ko_Kpzk-gbUzkOiFKNVhG6dAdswKC2mNUSjDeETBtIBcuVtk5wwFJYK7QKxpt_gBddyxQKtkfA1wq5w_QailNKnB4yH1MBrmAOKi2Us97MkyaZdcALZhh3aEBnza8iReVEJtCAUC25TSTgOsUjqG3lbllt8byIt_-CP-1xnzgsQsAsQ-7EHuVbX3QGsxH0lt4EuccCwnna7YmkDq_mKwChu_bV1lyUlcQSlWvJEtZHSOGlQA-JS2btqLqV0XuRol-prdPledCTeDqD4z0HAF_3aKRmKRi0WtaNnS2a2leC__a70Hs057GbIh3HZ4nej_dP6NJCqQ2CrZALJsXfmALjXJvUF8Xp87BZrXirFCwryRxCxYwTTII2KRqh8qBz6i1IdNty80yi-251tM2TXT-UlST0hmtlHTy70gGhG-tKR-jtwXvsTOiNN2o1Q-hm72XSiAWaEP4DWW67vNBp_1hb1nPEf3FmnYfb5vaJPWS_7NOvpiS6z9FtMRdqaKke1uW_T4U-6lW6IlEPnCzvLqq0_c_Uh9t_LGRf7_da4GQ8_Cl8y_iYbpH5AhXM3r9WUnDhvh9UsTG5HbZ5Wpwc3beNyiUOyHsmBpMvrMQHlenWIjjda-fxPnNNZ18aHlfo7I-NntCm_w_WzDSLPbLGy38LDnj_L1R6VItzx9bpoZ-w3rDrWp1BEATvDa0LKM65Oi9UT_2lXdCbHJ1faL0PWvU_NHi7NoBzeugt3H1pSjKq4FCQo2HQy-wszAB3jPJQma1wNvApou0fmuTDFb0kh_4CITuYn7k0nJ-IO_EqVH5-JP5AKEVeOEgQWCLRn8OZeAXndZq8Qar9bLa6RFf4T1L8xvclkYosg-k0Fw4YoTsumc-7kyIhdLd5_k7o7qToAa8qSD5u2-YRKsVXYBHj8_l8hiHnQRDP45jTGz5fpQnMwnARx63xdDr9DJqOuW37-jw4EockDmEar5aE3i6B0G37cQWHpb0W6UX1N1WtjFDuoHbDXn5p6wyyEghdfH32Mn_yBkLlT1oK_gbtW6fdTvjj4-toql7M2Q-0JyP2zOHV3rUvwvHCT9oro2Z8Bk4BOLN4mvZs6kS9XLcf9hiyeK9Dr3rbR82DttV-CFd8zTKLbgR3Y4cww5Q6zJlHVLkrzs9En6JveHgP4-3Pn3eY1s3N5X-1SLFbGs7tY6yjWXV9nHzRDmxt0B9yTXcaZFK-wYs2v213La4MWlS8mdwl40bbYJKuo3QVrdgE17MlpYtoGcfzSbGOwnmYLfgs5avZPFktGE2y2TKMltEimYcRnYg1DWkc3oSUUhqH82DlGy0J6TINE4qzlMQhlkzIQMp9GWiTT4S1Na5n4Wy5iCeSJSht89hFaVLnhFJ_e6G0baVoMzx3WL82v5uYtQ81TerckjiUwjo7BHfCSVz_V09iMKmNXBfOVba5-vkLai5cUScB16UfDHLfvU0ro_9C7gjdNYxYQncHUvZr-k8AAAD__12Sdpw">