//===- Redeclarable.h - Base for Decls that can be redeclared --*- C++ -*-====// // // 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 defines the Redeclarable interface. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_REDECLARABLE_H #define LLVM_CLANG_AST_REDECLARABLE_H #include "clang/AST/ExternalASTSource.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" #include <cassert> #include <cstddef> #include <iterator> namespace clang { class ASTContext; class Decl; // Some notes on redeclarables: // // - Every redeclarable is on a circular linked list. // // - Every decl has a pointer to the first element of the chain _and_ a // DeclLink that may point to one of 3 possible states: // - the "previous" (temporal) element in the chain // - the "latest" (temporal) element in the chain // - the "uninitialized-latest" value (when newly-constructed) // // - The first element is also often called the canonical element. Every // element has a pointer to it so that "getCanonical" can be fast. // // - Most links in the chain point to previous, except the link out of // the first; it points to latest. // // - Elements are called "first", "previous", "latest" or // "most-recent" when referring to temporal order: order of addition // to the chain. // // - It's easiest to just ignore the implementation of DeclLink when making // sense of the redeclaration chain. // // - There's also a "definition" link for several types of // redeclarable, where only one definition should exist at any given // time (and the defn pointer is stored in the decl's "data" which // is copied to every element on the chain when it's changed). // // Here is some ASCII art: // // "first" "latest" // "canonical" "most recent" // +------------+ first +--------------+ // | | <--------------------------- | | // | | | | // | | | | // | | +--------------+ | | // | | first | | | | // | | <---- | | | | // | | | | | | // | @class A | link | @interface A | link | @class A | // | seen first | <---- | seen second | <---- | seen third | // | | | | | | // +------------+ +--------------+ +--------------+ // | data | defn | data | defn | data | // | | ----> | | <---- | | // +------------+ +--------------+ +--------------+ // | | ^ ^ // | |defn | | // | link +-----+ | // +-->-------------------------------------------+ /// Provides common interface for the Decls that can be redeclared. template<typename decl_type> class Redeclarable { … }; /// Get the primary declaration for a declaration from an AST file. That /// will be the first-loaded declaration. Decl *getPrimaryMergedDecl(Decl *D); /// Provides common interface for the Decls that cannot be redeclared, /// but can be merged if the same declaration is brought in from multiple /// modules. template<typename decl_type> class Mergeable { … }; /// A wrapper class around a pointer that always points to its canonical /// declaration. /// /// CanonicalDeclPtr<decl_type> behaves just like decl_type*, except we call /// decl_type::getCanonicalDecl() on construction. /// /// This is useful for hashtables that you want to be keyed on a declaration's /// canonical decl -- if you use CanonicalDeclPtr as the key, you don't need to /// remember to call getCanonicalDecl() everywhere. template <typename decl_type> class CanonicalDeclPtr { … }; } // namespace clang namespace llvm { DenseMapInfo<clang::CanonicalDeclPtr<decl_type>>; PointerLikeTypeTraits<clang::CanonicalDeclPtr<decl_type>>; } // namespace llvm #endif // LLVM_CLANG_AST_REDECLARABLE_H