Repository: carbon-language/carbon-lang
File: toolchain/sem_ir/clang_decl.h (C/C++)

Code before:

#include "common/hashtable_key_context.h"
#include "common/ostream.h"
#include "toolchain/sem_ir/ids.h"

// NOLINTNEXTLINE(readability-identifier-naming)
namespace clang {

// Forward declare indexed types, for integration with ValueStore.
class Decl;

}  // namespace clang

namespace Carbon::SemIR {

// A Clang declaration mapped to a Carbon instruction.
//
// Note that Clang's AST uses address-identity for nodes, which means the
// pointer is the canonical way to represent a specific AST node and is expected
// to be sufficient for comparison, hashing, etc.
struct ClangDecl : public Printable<ClangDecl> {
  auto Print(llvm::raw_ostream& out) const -> void;

  // Equality comparison uses the address-identity property of the Clang AST and
  // just compares the `decl` pointers. We canonicalize on these to avoid ever
  // having different instructions for the same declaration.
  auto operator==(const ClangDecl& rhs) const -> bool {
    return decl == rhs.decl;
  }
  // Support direct comparison with the Clang AST node pointer.
  auto operator==(const clang::Decl* rhs_decl) const -> bool {
    return decl == rhs_decl;
  }

  // Hashing for ClangDecl. See common/hashing.h.
  friend auto CarbonHashValue(const ClangDecl& value, uint64_t seed)
      -> HashCode {
    return HashValue(value.decl, seed);
  }

  // The Clang declaration pointing to the Clang AST.
  // TODO: Ensure we can easily serialize/deserialize this. Consider
  // `clang::LazyDeclPtr`.
  clang::Decl* decl = nullptr;

  // The instruction the Clang declaration is mapped to.
  //
  // This is stored along side the `decl` pointer to avoid having to lookup both
  // the pointer and the instruction ID in two separate areas of storage.
  InstId inst_id;
};

Review comment (suggestion):
```suggestion
  // Equality comparison uses the address-identity property of the Clang AST and
  // just compares the `decl` pointers. We can disregard `inst_id` because `ClangDecl`s
  // are only used as entries in `SemIR::clang_decls`, which canonicalizes them to
  // ensure that the same `decl` can't be associated with more than one `inst_id`.
```

Code after:

#include "common/hashtable_key_context.h"
#include "common/ostream.h"
#include "toolchain/sem_ir/ids.h"

// NOLINTNEXTLINE(readability-identifier-naming)
namespace clang {

// Forward declare indexed types, for integration with ValueStore.
class Decl;

}  // namespace clang

namespace Carbon::SemIR {

// A Clang declaration mapped to a Carbon instruction.
//
// Note that Clang's AST uses address-identity for nodes, which means the
// pointer is the canonical way to represent a specific AST node and is expected
// to be sufficient for comparison, hashing, etc.
//
// This type is specifically designed for use in a `CanonicalValueStore` and
// provide a single canonical access from SemIR to each `clang::Decl*` used.
// This also ensures that a given `clang::Decl*` is associated with exactly one
// instruction, and the `inst_id` here provides access to that instruction from
// either the `ClangDeclId` or the `clang::Decl*`.
struct ClangDecl : public Printable<ClangDecl> {
  auto Print(llvm::raw_ostream& out) const -> void;

  // Equality comparison uses the address-identity property of the Clang AST and
  // just compares the `decl` pointers. The `inst_id` is always the same due to
  // the canonicalization.
  auto operator==(const ClangDecl& rhs) const -> bool {
    return decl == rhs.decl;
  }
  // Support direct comparison with the Clang AST node pointer.
  auto operator==(const clang::Decl* rhs_decl) const -> bool {
    return decl == rhs_decl;
  }

  // Hashing for ClangDecl. See common/hashing.h.
  friend auto CarbonHashValue(const ClangDecl& value, uint64_t seed)
      -> HashCode {
    return HashValue(value.decl, seed);
  }

  // The Clang declaration pointing to the Clang AST.
  // TODO: Ensure we can easily serialize/deserialize this. Consider
  // `clang::LazyDeclPtr`.
  clang::Decl* decl = nullptr;