Skip to content

Conversation

@SergejSalnikov
Copy link
Contributor

@SergejSalnikov SergejSalnikov commented Nov 5, 2025

writeBareSourceLocation is always called on either Expanded or Spelling location, in any on those cases the
SM.getSpellingLineNumber(Loc) == SM.getExpansionLineNumber(Loc) == SM.getLineNumber(Loc).

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 5, 2025

@llvm/pr-subscribers-clang

Author: SKill (SergejSalnikov)

Changes

Patch is 89.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/166588.diff

2 Files Affected:

  • (modified) clang/include/clang/AST/JSONNodeDumper.h (+1-1)
  • (modified) clang/lib/AST/JSONNodeDumper.cpp (+435-1865)
diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h
index 427a9c51ece1b..d364795a05811 100644
--- a/clang/include/clang/AST/JSONNodeDumper.h
+++ b/clang/include/clang/AST/JSONNodeDumper.h
@@ -149,7 +149,7 @@ class JSONNodeDumper
   void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
 
   // Writes the attributes of a SourceLocation object without.
-  void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
+  void writeBareSourceLocation(SourceLocation Loc);
 
   // Writes the attributes of a SourceLocation to JSON based on its presumed
   // spelling location. If the given location represents a macro invocation,
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 9f4dba9f14fa6..d364795a05811 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -1,1894 +1,464 @@
-#include "clang/AST/JSONNodeDumper.h"
+//===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AST dumping of components of individual AST nodes to
+// a JSON.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
+#define LLVM_CLANG_AST_JSONNODEDUMPER_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDumperUtils.h"
+#include "clang/AST/ASTNodeTraverser.h"
+#include "clang/AST/AttrVisitor.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/CommentVisitor.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Mangle.h"
 #include "clang/AST/Type.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/JSON.h"
 
-using namespace clang;
+namespace clang {
 
-void JSONNodeDumper::addPreviousDeclaration(const Decl *D) {
-  switch (D->getKind()) {
-#define DECL(DERIVED, BASE)                                                    \
-  case Decl::DERIVED:                                                          \
-    return writePreviousDeclImpl(cast<DERIVED##Decl>(D));
-#define ABSTRACT_DECL(DECL)
-#include "clang/AST/DeclNodes.inc"
-#undef ABSTRACT_DECL
-#undef DECL
-  }
-  llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
-}
-
-void JSONNodeDumper::Visit(const Attr *A) {
-  const char *AttrName = nullptr;
-  switch (A->getKind()) {
-#define ATTR(X)                                                                \
-  case attr::X:                                                                \
-    AttrName = #X"Attr";                                                       \
-    break;
-#include "clang/Basic/AttrList.inc"
-#undef ATTR
-  }
-  JOS.attribute("id", createPointerRepresentation(A));
-  JOS.attribute("kind", AttrName);
-  JOS.attributeObject("range", [A, this] { writeSourceRange(A->getRange()); });
-  attributeOnlyIfTrue("inherited", A->isInherited());
-  attributeOnlyIfTrue("implicit", A->isImplicit());
-
-  // FIXME: it would be useful for us to output the spelling kind as well as
-  // the actual spelling. This would allow us to distinguish between the
-  // various attribute syntaxes, but we don't currently track that information
-  // within the AST.
-  //JOS.attribute("spelling", A->getSpelling());
-
-  InnerAttrVisitor::Visit(A);
-}
-
-void JSONNodeDumper::Visit(const Stmt *S) {
-  if (!S)
-    return;
-
-  JOS.attribute("id", createPointerRepresentation(S));
-  JOS.attribute("kind", S->getStmtClassName());
-  JOS.attributeObject("range",
-                      [S, this] { writeSourceRange(S->getSourceRange()); });
-
-  if (const auto *E = dyn_cast<Expr>(S)) {
-    JOS.attribute("type", createQualType(E->getType()));
-    const char *Category = nullptr;
-    switch (E->getValueKind()) {
-    case VK_LValue: Category = "lvalue"; break;
-    case VK_XValue: Category = "xvalue"; break;
-    case VK_PRValue:
-      Category = "prvalue";
-      break;
-    }
-    JOS.attribute("valueCategory", Category);
-  }
-  InnerStmtVisitor::Visit(S);
-}
-
-void JSONNodeDumper::Visit(const Type *T) {
-  JOS.attribute("id", createPointerRepresentation(T));
-
-  if (!T)
-    return;
-
-  JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str());
-  JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar=*/false));
-  attributeOnlyIfTrue("containsErrors", T->containsErrors());
-  attributeOnlyIfTrue("isDependent", T->isDependentType());
-  attributeOnlyIfTrue("isInstantiationDependent",
-                      T->isInstantiationDependentType());
-  attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType());
-  attributeOnlyIfTrue("containsUnexpandedPack",
-                      T->containsUnexpandedParameterPack());
-  attributeOnlyIfTrue("isImported", T->isFromAST());
-  InnerTypeVisitor::Visit(T);
-}
-
-void JSONNodeDumper::Visit(QualType T) {
-  JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
-  JOS.attribute("kind", "QualType");
-  JOS.attribute("type", createQualType(T));
-  JOS.attribute("qualifiers", T.split().Quals.getAsString());
-}
-
-void JSONNodeDumper::Visit(TypeLoc TL) {
-  if (TL.isNull())
-    return;
-  JOS.attribute("kind",
-                (llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified
-                                 ? "Qualified"
-                                 : TL.getTypePtr()->getTypeClassName()) +
-                 "TypeLoc")
-                    .str());
-  JOS.attribute("type",
-                createQualType(QualType(TL.getType()), /*Desugar=*/false));
-  JOS.attributeObject("range",
-                      [TL, this] { writeSourceRange(TL.getSourceRange()); });
-}
-
-void JSONNodeDumper::Visit(const Decl *D) {
-  JOS.attribute("id", createPointerRepresentation(D));
-
-  if (!D)
-    return;
-
-  JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
-  JOS.attributeObject("loc",
-                      [D, this] { writeSourceLocation(D->getLocation()); });
-  JOS.attributeObject("range",
-                      [D, this] { writeSourceRange(D->getSourceRange()); });
-  attributeOnlyIfTrue("isImplicit", D->isImplicit());
-  attributeOnlyIfTrue("isInvalid", D->isInvalidDecl());
-
-  if (D->isUsed())
-    JOS.attribute("isUsed", true);
-  else if (D->isThisDeclarationReferenced())
-    JOS.attribute("isReferenced", true);
-
-  if (const auto *ND = dyn_cast<NamedDecl>(D))
-    attributeOnlyIfTrue("isHidden", !ND->isUnconditionallyVisible());
-
-  if (D->getLexicalDeclContext() != D->getDeclContext()) {
-    // Because of multiple inheritance, a DeclContext pointer does not produce
-    // the same pointer representation as a Decl pointer that references the
-    // same AST Node.
-    const auto *ParentDeclContextDecl = dyn_cast<Decl>(D->getDeclContext());
-    JOS.attribute("parentDeclContextId",
-                  createPointerRepresentation(ParentDeclContextDecl));
-  }
-
-  addPreviousDeclaration(D);
-  InnerDeclVisitor::Visit(D);
-}
-
-void JSONNodeDumper::Visit(const comments::Comment *C,
-                           const comments::FullComment *FC) {
-  if (!C)
-    return;
-
-  JOS.attribute("id", createPointerRepresentation(C));
-  JOS.attribute("kind", C->getCommentKindName());
-  JOS.attributeObject("loc",
-                      [C, this] { writeSourceLocation(C->getLocation()); });
-  JOS.attributeObject("range",
-                      [C, this] { writeSourceRange(C->getSourceRange()); });
-
-  InnerCommentVisitor::visit(C, FC);
-}
-
-void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
-                           const Decl *From, StringRef Label) {
-  JOS.attribute("kind", "TemplateArgument");
-  if (R.isValid())
-    JOS.attributeObject("range", [R, this] { writeSourceRange(R); });
-
-  if (From)
-    JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From));
-
-  InnerTemplateArgVisitor::Visit(TA);
-}
-
-void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
-  JOS.attribute("kind", "CXXCtorInitializer");
-  if (Init->isAnyMemberInitializer())
-    JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));
-  else if (Init->isBaseInitializer())
-    JOS.attribute("baseInit",
-                  createQualType(QualType(Init->getBaseClass(), 0)));
-  else if (Init->isDelegatingInitializer())
-    JOS.attribute("delegatingInit",
-                  createQualType(Init->getTypeSourceInfo()->getType()));
-  else
-    llvm_unreachable("Unknown initializer type");
-}
-
-void JSONNodeDumper::Visit(const OpenACCClause *C) {}
-
-void JSONNodeDumper::Visit(const OMPClause *C) {}
-
-void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
-  JOS.attribute("kind", "Capture");
-  attributeOnlyIfTrue("byref", C.isByRef());
-  attributeOnlyIfTrue("nested", C.isNested());
-  if (C.getVariable())
-    JOS.attribute("var", createBareDeclRef(C.getVariable()));
-}
-
-void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
-  JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default");
-  attributeOnlyIfTrue("selected", A.isSelected());
-}
-
-void JSONNodeDumper::Visit(const concepts::Requirement *R) {
-  if (!R)
-    return;
-
-  switch (R->getKind()) {
-  case concepts::Requirement::RK_Type:
-    JOS.attribute("kind", "TypeRequirement");
-    break;
-  case concepts::Requirement::RK_Simple:
-    JOS.attribute("kind", "SimpleRequirement");
-    break;
-  case concepts::Requirement::RK_Compound:
-    JOS.attribute("kind", "CompoundRequirement");
-    break;
-  case concepts::Requirement::RK_Nested:
-    JOS.attribute("kind", "NestedRequirement");
-    break;
-  }
-
-  if (auto *ER = dyn_cast<concepts::ExprRequirement>(R))
-    attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement());
-
-  attributeOnlyIfTrue("isDependent", R->isDependent());
-  if (!R->isDependent())
-    JOS.attribute("satisfied", R->isSatisfied());
-  attributeOnlyIfTrue("containsUnexpandedPack",
-                      R->containsUnexpandedParameterPack());
-}
-
-void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
-  std::string Str;
-  llvm::raw_string_ostream OS(Str);
-  Value.printPretty(OS, Ctx, Ty);
-  JOS.attribute("value", Str);
-}
-
-void JSONNodeDumper::Visit(const ConceptReference *CR) {
-  JOS.attribute("kind", "ConceptReference");
-  JOS.attribute("id", createPointerRepresentation(CR->getNamedConcept()));
-  if (const auto *Args = CR->getTemplateArgsAsWritten()) {
-    JOS.attributeArray("templateArgsAsWritten", [Args, this] {
-      for (const TemplateArgumentLoc &TAL : Args->arguments())
-        JOS.object(
-            [&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });
-    });
-  }
-  JOS.attributeObject("loc",
-                      [CR, this] { writeSourceLocation(CR->getLocation()); });
-  JOS.attributeObject("range",
-                      [CR, this] { writeSourceRange(CR->getSourceRange()); });
-}
-
-void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
-  if (Loc.isInvalid())
-    return;
-
-  JOS.attributeBegin("includedFrom");
-  JOS.objectBegin();
-
-  if (!JustFirst) {
-    // Walk the stack recursively, then print out the presumed location.
-    writeIncludeStack(SM.getPresumedLoc(Loc.getIncludeLoc()));
-  }
-
-  JOS.attribute("file", Loc.getFilename());
-  JOS.objectEnd();
-  JOS.attributeEnd();
-}
-
-void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc,
-                                             bool IsSpelling) {
-  PresumedLoc Presumed = SM.getPresumedLoc(Loc);
-  unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc)
-                                   : SM.getExpansionLineNumber(Loc);
-  StringRef ActualFile = SM.getBufferName(Loc);
-
-  if (Presumed.isValid()) {
-    JOS.attribute("offset", SM.getDecomposedLoc(Loc).second);
-    if (LastLocFilename != ActualFile) {
-      JOS.attribute("file", ActualFile);
-      JOS.attribute("line", ActualLine);
-    } else if (LastLocLine != ActualLine)
-      JOS.attribute("line", ActualLine);
-
-    StringRef PresumedFile = Presumed.getFilename();
-    if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile)
-      JOS.attribute("presumedFile", PresumedFile);
-
-    unsigned PresumedLine = Presumed.getLine();
-    if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine)
-      JOS.attribute("presumedLine", PresumedLine);
-
-    JOS.attribute("col", Presumed.getColumn());
-    JOS.attribute("tokLen",
-                  Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts()));
-    LastLocFilename = ActualFile;
-    LastLocPresumedFilename = PresumedFile;
-    LastLocPresumedLine = PresumedLine;
-    LastLocLine = ActualLine;
-
-    // Orthogonal to the file, line, and column de-duplication is whether the
-    // given location was a result of an include. If so, print where the
-    // include location came from.
-    writeIncludeStack(SM.getPresumedLoc(Presumed.getIncludeLoc()),
-                      /*JustFirst*/ true);
-  }
-}
-
-void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {
-  SourceLocation Spelling = SM.getSpellingLoc(Loc);
-  SourceLocation Expansion = SM.getExpansionLoc(Loc);
-
-  if (Expansion != Spelling) {
-    // If the expansion and the spelling are different, output subobjects
-    // describing both locations.
-    JOS.attributeObject("spellingLoc", [Spelling, this] {
-      writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
-    });
-    JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {
-      writeBareSourceLocation(Expansion, /*IsSpelling*/ false);
-      // If there is a macro expansion, add extra information if the interesting
-      // bit is the macro arg expansion.
-      if (SM.isMacroArgExpansion(Loc))
-        JOS.attribute("isMacroArgExpansion", true);
-    });
-  } else
-    writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
-}
-
-void JSONNodeDumper::writeSourceRange(SourceRange R) {
-  JOS.attributeObject("begin",
-                      [R, this] { writeSourceLocation(R.getBegin()); });
-  JOS.attributeObject("end", [R, this] { writeSourceLocation(R.getEnd()); });
-}
-
-std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {
-  // Because JSON stores integer values as signed 64-bit integers, trying to
-  // represent them as such makes for very ugly pointer values in the resulting
-  // output. Instead, we convert the value to hex and treat it as a string.
-  return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr), true);
-}
-
-llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {
-  SplitQualType SQT = QT.split();
-  std::string SQTS = QualType::getAsString(SQT, PrintPolicy);
-  llvm::json::Object Ret{{"qualType", SQTS}};
-
-  if (Desugar && !QT.isNull()) {
-    SplitQualType DSQT = QT.getSplitDesugaredType();
-    if (DSQT != SQT) {
-      std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
-      if (DSQTS != SQTS)
-        Ret["desugaredQualType"] = DSQTS;
-    }
-    if (const auto *TT = QT->getAs<TypedefType>())
-      Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl());
-  }
-  return Ret;
-}
-
-void JSONNodeDumper::writeBareDeclRef(const Decl *D) {
-  JOS.attribute("id", createPointerRepresentation(D));
-  if (!D)
-    return;
-
-  JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
-  if (const auto *ND = dyn_cast<NamedDecl>(D))
-    JOS.attribute("name", ND->getDeclName().getAsString());
-  if (const auto *VD = dyn_cast<ValueDecl>(D))
-    JOS.attribute("type", createQualType(VD->getType()));
-}
-
-llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {
-  llvm::json::Object Ret{{"id", createPointerRepresentation(D)}};
-  if (!D)
-    return Ret;
-
-  Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str();
-  if (const auto *ND = dyn_cast<NamedDecl>(D))
-    Ret["name"] = ND->getDeclName().getAsString();
-  if (const auto *VD = dyn_cast<ValueDecl>(D))
-    Ret["type"] = createQualType(VD->getType());
-  return Ret;
-}
-
-llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) {
-  llvm::json::Array Ret;
-  if (C->path_empty())
-    return Ret;
-
-  for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) {
-    const CXXBaseSpecifier *Base = *I;
-    const auto *RD = cast<CXXRecordDecl>(
-        Base->getType()->castAsCanonical<RecordType>()->getDecl());
-
-    llvm::json::Object Val{{"name", RD->getName()}};
-    if (Base->isVirtual())
-      Val["isVirtual"] = true;
-    Ret.push_back(std::move(Val));
-  }
-  return Ret;
-}
+class APValue;
 
-#define FIELD2(Name, Flag)  if (RD->Flag()) Ret[Name] = true
-#define FIELD1(Flag)        FIELD2(#Flag, Flag)
+class NodeStreamer {
+  bool FirstChild = true;
+  bool TopLevel = true;
+  llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
 
-static llvm::json::Object
-createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) {
-  llvm::json::Object Ret;
+protected:
+  llvm::json::OStream JOS;
 
-  FIELD2("exists", hasDefaultConstructor);
-  FIELD2("trivial", hasTrivialDefaultConstructor);
-  FIELD2("nonTrivial", hasNonTrivialDefaultConstructor);
-  FIELD2("userProvided", hasUserProvidedDefaultConstructor);
-  FIELD2("isConstexpr", hasConstexprDefaultConstructor);
-  FIELD2("needsImplicit", needsImplicitDefaultConstructor);
-  FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr);
-
-  return Ret;
-}
-
-static llvm::json::Object
-createCopyConstructorDefinitionData(const CXXRecordDecl *RD) {
-  llvm::json::Object Ret;
-
-  FIELD2("simple", hasSimpleCopyConstructor);
-  FIELD2("trivial", hasTrivialCopyConstructor);
-  FIELD2("nonTrivial", hasNonTrivialCopyConstructor);
-  FIELD2("userDeclared", hasUserDeclaredCopyConstructor);
-  FIELD2("hasConstParam", hasCopyConstructorWithConstParam);
-  FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam);
-  FIELD2("needsImplicit", needsImplicitCopyConstructor);
-  FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor);
-  if (!RD->needsOverloadResolutionForCopyConstructor())
-    FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted);
-
-  return Ret;
-}
-
-static llvm::json::Object
-createMoveConstructorDefinitionData(const CXXRecordDecl *RD) {
-  llvm::json::Object Ret;
-
-  FIELD2("exists", hasMoveConstructor);
-  FIELD2("simple", hasSimpleMoveConstructor);
-  FIELD2("trivial", hasTrivialMoveConstructor);
-  FIELD2("nonTrivial", hasNonTrivialMoveConstructor);
-  FIELD2("userDeclared", hasUserDeclaredMoveConstructor);
-  FIELD2("needsImplicit", needsImplicitMoveConstructor);
-  FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor);
-  if (!RD->needsOverloadResolutionForMoveConstructor())
-    FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted);
-
-  return Ret;
-}
-
-static llvm::json::Object
-createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {
-  llvm::json::Object Ret;
-
-  FIELD2("simple", hasSimpleCopyAssignment);
-  FIELD2("trivial", hasTrivialCopyAssignment);
-  FIELD2("nonTrivial", hasNonTrivialCopyAssignment);
-  FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);
-  FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam);
-  FIELD2("userDeclared", hasUserDeclaredCopyAssignment);
-  FIELD2("needsImplicit", needsImplicitCopyAssignment);
-  FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment);
-
-  return Ret;
-}
-
-static llvm::json::Object
-createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) {
-  llvm::json::Object Ret;
-
-  FIELD2("exists", hasMoveAssignment);
-  FIELD2("simple", hasSimpleMoveAssignment);
-  FIELD2("trivial", hasTrivialMoveAssignment);
-  FIELD2("nonTrivial", hasNonTrivialMoveAssignment);
-  FIELD2("userDeclared", hasUserDeclaredMoveAssignment);
-  FIELD2("needsImplicit", needsImplicitMoveAssignment);
-  FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment);
-
-  return Ret;
-}
-
-static llvm::json::Object
-createDestructorDefinitionData(const C...
[truncated]

@github-actions
Copy link

github-actions bot commented Nov 5, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@Fznamznon Fznamznon left a comment

Choose a reason for hiding this comment

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

Hi, could you please give a bit more context, i.e. perhaps explain what is going on and why the cases are impossible? It would be great to add this info to the PR description.

@SergejSalnikov
Copy link
Contributor Author

Hi, could you please give a bit more context, i.e. perhaps explain what is going on and why the cases are impossible? It would be great to add this info to the PR description.

PTAL.

@SergejSalnikov SergejSalnikov changed the title [clang][AST] Do not try to handle impossible cases in writeBareSourceLocation [clang][AST] Do not try to handle irrelevant cases in writeBareSourceLocation Nov 6, 2025
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

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

LGTM, good catch!

@AaronBallman AaronBallman merged commit 6ac4585 into llvm:main Nov 6, 2025
10 checks passed
vinay-deshmukh pushed a commit to vinay-deshmukh/llvm-project that referenced this pull request Nov 8, 2025
…Location (llvm#166588)

`writeBareSourceLocation` is always called on either `Expanded` or
`Spelling` location, in any on those cases the
`SM.getSpellingLineNumber(Loc) == SM.getExpansionLineNumber(Loc) ==
SM.getLineNumber(Loc)`.
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.

4 participants