Skip to content

[clang][AST] Fix end location of DeclarationNameInfo on instantiated methods #92654

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

Merged
merged 1 commit into from
May 22, 2024
Merged

[clang][AST] Fix end location of DeclarationNameInfo on instantiated methods #92654

merged 1 commit into from
May 22, 2024

Conversation

steakhal
Copy link
Contributor

Fixes #71161

D64087 updated some locations of the instantiated method but forgot DNLoc.

FunctionDecl::getNameInfo() constructs a DeclarationNameInfo using Decl::Loc as the beginning of the declaration name, and FunctionDecl::DNLoc to compute the end of the declaration name. The former was updated, but the latter was not, so DeclarationName::getSourceRange() would return a range where the end of the declaration name could come before its beginning.

Patch by Alejandro Alvarez Ayllon
Co-authored-by: steakhal

CPP-5166

@steakhal steakhal added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 18, 2024
@llvmbot
Copy link
Member

llvmbot commented May 18, 2024

@llvm/pr-subscribers-clang

Author: Balazs Benics (steakhal)

Changes

Fixes #71161

D64087 updated some locations of the instantiated method but forgot DNLoc.

FunctionDecl::getNameInfo() constructs a DeclarationNameInfo using Decl::Loc as the beginning of the declaration name, and FunctionDecl::DNLoc to compute the end of the declaration name. The former was updated, but the latter was not, so DeclarationName::getSourceRange() would return a range where the end of the declaration name could come before its beginning.

Patch by Alejandro Alvarez Ayllon
Co-authored-by: steakhal

CPP-5166


Full diff: https://github.com/llvm/llvm-project/pull/92654.diff

3 Files Affected:

  • (modified) clang/include/clang/AST/Decl.h (+2)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+1)
  • (modified) clang/unittests/AST/DeclTest.cpp (+31)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 5e485ccb85a13..7fd80b90d1033 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -2188,6 +2188,8 @@ class FunctionDecl : public DeclaratorDecl,
 
   void setRangeEnd(SourceLocation E) { EndRangeLoc = E; }
 
+  void setDeclarationNameLoc(DeclarationNameLoc L) { DNLoc = L; }
+
   /// Returns the location of the ellipsis of a variadic function.
   SourceLocation getEllipsisLoc() const {
     const auto *FPT = getType()->getAs<FunctionProtoType>();
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 381d79b2fcd46..6d736d0771eac 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5055,6 +5055,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
   Function->setLocation(PatternDecl->getLocation());
   Function->setInnerLocStart(PatternDecl->getInnerLocStart());
   Function->setRangeEnd(PatternDecl->getEndLoc());
+  Function->setDeclarationNameLoc(PatternDecl->getNameInfo().getInfo());
 
   EnterExpressionEvaluationContext EvalContext(
       *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 2530ce74eb6a3..16aa2b50b7a06 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -545,3 +545,34 @@ TEST(Decl, TemplateArgumentDefaulted) {
   EXPECT_TRUE(ArgList.get(2).getIsDefaulted());
   EXPECT_TRUE(ArgList.get(3).getIsDefaulted());
 }
+
+TEST(Decl, CXXDestructorDeclsShouldHaveWellFormedNameInfoRanges) {
+  // GH71161
+  llvm::Annotations Code(R"cpp(
+template <typename T> struct Resource {
+  ~Resource(); // 1
+};
+template <typename T>
+Resource<T>::~Resource() {} // 2,3
+
+void instantiate_template() {
+  Resource<int> x;
+}
+)cpp");
+
+  auto AST = tooling::buildASTFromCode(Code.code());
+  ASTContext &Ctx = AST->getASTContext();
+
+  const auto &SM = Ctx.getSourceManager();
+  auto GetNameInfoRange = [&SM](const BoundNodes &Match) {
+    const auto *D = Match.getNodeAs<CXXDestructorDecl>("dtor");
+    return D->getNameInfo().getSourceRange().printToString(SM);
+  };
+
+  auto Matches = match(findAll(cxxDestructorDecl().bind("dtor")),
+                       *Ctx.getTranslationUnitDecl(), Ctx);
+  ASSERT_EQ(Matches.size(), 3U);
+  EXPECT_EQ(GetNameInfoRange(Matches[0]), "<input.cc:3:3, col:4>");
+  EXPECT_EQ(GetNameInfoRange(Matches[1]), "<input.cc:6:14, col:15>");
+  EXPECT_EQ(GetNameInfoRange(Matches[2]), "<input.cc:6:14, col:15>");
+}

Copy link
Contributor

@Endilll Endilll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but wait for more reviews.

Copy link
Collaborator

@hokein hokein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add a note in clang/docs/ReleaseNotes.rst

@steakhal
Copy link
Contributor Author

nit: add a note in clang/docs/ReleaseNotes.rst

Thanks. Added. Let me know if it's in the right section. @hokein

…methods

Fixes #71161

[D64087](https://reviews.llvm.org/D64087) updated some locations of the
instantiated method but forgot `DNLoc`.

`FunctionDecl::getNameInfo()` constructs a `DeclarationNameInfo` using
`Decl::Loc` as the beginning of the declaration name, and
`FunctionDecl::DNLoc` to compute the end of the declaration name. The
former was updated, but the latter was not, so
`DeclarationName::getSourceRange()` would return a range where the end
of the declaration name could come before its beginning.

Patch by Alejandro Alvarez Ayllon
Co-authored-by: steakhal

CPP-5166
@steakhal steakhal merged commit 919df9d into llvm:main May 22, 2024
4 of 5 checks passed
@steakhal steakhal deleted the fix-gh-71161-invalid-dtor-loc branch May 22, 2024 15:41
@Abramo-Bagnara
Copy link
Contributor

@alejandro-alvarez-sonarsource @steakhal

This breaks the type info loaded correctly in previous decl instantiation:

template <typename T>
struct s {
  operator T();
    return 0;
  }
};

void f() {
  s<int> x;
  (int)x;
}

In this case the instantiated conversion DeclarationNameInfo is reverted back to template parameter T, instead of correct SubstTemplateTypeParmType.

@steakhal
Copy link
Contributor Author

@alejandro-alvarez-sonarsource @steakhal

This breaks the type info loaded correctly in previous decl instantiation: [...]

Thank you for reporting @Abramo-Bagnara. Could you create a dedicated GH issue for this please?
FYI: I don't have plans to work on it though, but someone else may would want to pick it up, thus a dedicated ticket would bring visibility and opportunity to someone to work on. Thank you.

@zyn0217
Copy link
Contributor

zyn0217 commented Apr 3, 2025

@Abramo-Bagnara @steakhal I noticed the same issue and I have posted the fix in #134038

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang] Wrong SourceRange returned by getNameInfo() for template instantiations of CXXDestructorDecls
8 participants