diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 77ba81c58c5d63f7e5e054d9503e882afd3ae468..76b8266cae87c4b0b3fbf90e4bf72626aad7c9f3 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -125,3 +125,6 @@ clang/test/AST/Interp/ @tbaederr
/llvm/**/TextAPI/ @cyndyishida
/clang/**/InstallAPI/ @cyndyishida
/clang/tools/clang-installapi/ @cyndyishida
+
+# ExtractAPI
+/clang/**/ExtractAPI @daniel-grumberg
diff --git a/.github/workflows/email-check.yaml b/.github/workflows/email-check.yaml
index ac53b5e527b0949020e0e73d90def5d2b6295cd0..8f32d020975f5d70e7eead9c34a0ea86fb836e81 100644
--- a/.github/workflows/email-check.yaml
+++ b/.github/workflows/email-check.yaml
@@ -1,7 +1,7 @@
name: "Check for private emails used in PRs"
on:
- pull_request_target:
+ pull_request:
types:
- opened
@@ -10,8 +10,6 @@ permissions:
jobs:
validate_email:
- permissions:
- pull-requests: write
runs-on: ubuntu-latest
if: github.repository == 'llvm/llvm-project'
steps:
@@ -25,20 +23,24 @@ jobs:
run: |
git log -1
echo "EMAIL=$(git show -s --format='%ae' HEAD~0)" >> $GITHUB_OUTPUT
+ # Create empty comment file
+ echo "[]" > comments
- name: Validate author email
if: ${{ endsWith(steps.author.outputs.EMAIL, 'noreply.github.com') }}
- uses: actions/github-script@v6
env:
- EMAIL: ${{ steps.author.outputs.EMAIL }}
+ COMMENT: >-
+ ⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
+ Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account.
+ See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information.
+ run: |
+ cat << EOF > comments
+ [{"body" : "$COMMENT"}]
+ EOF
+
+ - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ if: always()
with:
- script: |
- const { EMAIL } = process.env
- await github.rest.issues.createComment({
- issue_number: context.issue.number,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: `⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
- Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account.
- See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information.
- `})
+ name: workflow-args
+ path: |
+ comments
diff --git a/.github/workflows/issue-write.yml b/.github/workflows/issue-write.yml
index 4a564a5076bac9a7855d69b59a1a60f088300163..e003be006c4e15405bd977e277b0f9a64e69d2af 100644
--- a/.github/workflows/issue-write.yml
+++ b/.github/workflows/issue-write.yml
@@ -2,7 +2,9 @@ name: Comment on an issue
on:
workflow_run:
- workflows: ["Check code formatting"]
+ workflows:
+ - "Check code formatting"
+ - "Check for private emails used in PRs"
types:
- completed
diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml
index 54dfe3aadbb423d98b106ea02d9f4f09e25574c3..10b18f245d8965a69251038f44f1505fc40c0cf0 100644
--- a/.github/workflows/pr-code-format.yml
+++ b/.github/workflows/pr-code-format.yml
@@ -33,7 +33,7 @@ jobs:
- name: Fetch code formatting utils
uses: actions/checkout@v4
with:
- reository: ${{ github.repository }}
+ repository: ${{ github.repository }}
ref: ${{ github.base_ref }}
sparse-checkout: |
llvm/utils/git/requirements_formatting.txt
diff --git a/clang-tools-extra/clangd/IncludeCleaner.h b/clang-tools-extra/clangd/IncludeCleaner.h
index 387763de340767be7e3cf8598db2b1a6c7076fd5..624e2116be7da3015816dfec628d8de6ac7f363c 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.h
+++ b/clang-tools-extra/clangd/IncludeCleaner.h
@@ -62,15 +62,6 @@ issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code,
const ThreadsafeFS &TFS,
HeaderFilter IgnoreHeader = {});
-/// Affects whether standard library includes should be considered for
-/// removal. This is off by default for now due to implementation limitations:
-/// - macros are not tracked
-/// - symbol names without a unique associated header are not tracked
-/// - references to std-namespaced C types are not properly tracked:
-/// instead of std::size_t -> we see ::size_t ->
-/// FIXME: remove this hack once the implementation is good enough.
-void setIncludeCleanerAnalyzesStdlib(bool B);
-
/// Converts the clangd include representation to include-cleaner
/// include representation.
include_cleaner::Includes convertIncludes(const ParsedAST &);
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca7637538859ab4865eaa3e28e44a60bf1..57d930b26e64c0f1920ff932e18e48e279a0ec0e 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -25,7 +25,7 @@
// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck --check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 | FileCheck -check-prefix=CHECK8 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602
// CHECK1: error: no input files [clang-diagnostic-error]
// CHECK1: error: no such file or directory: '{{.*}}nonexistent.cpp' [clang-diagnostic-error]
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
{
return 1;
}
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
#endif
diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake
index df69d7d0dd414beb8be6752acae171cf6fd5272e..393d97a4cf1a3302db9be62d1982d0f485d52a3b 100644
--- a/clang/cmake/caches/Fuchsia.cmake
+++ b/clang/cmake/caches/Fuchsia.cmake
@@ -71,6 +71,8 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH
Python3_LIBRARIES
Python3_INCLUDE_DIRS
Python3_RPATH
+ SWIG_DIR
+ SWIG_EXECUTABLE
CMAKE_FIND_PACKAGE_PREFER_CONFIG
CMAKE_SYSROOT
CMAKE_MODULE_LINKER_FLAGS
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 2ee36f24d7ce4b37c4bdf56ba318549b48696a80..39f7cded36edbff5846925aa56319682a04ed476 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3295,6 +3295,21 @@ the configuration (without a prefix: ``Auto``).
+.. _BreakFunctionDefinitionParameters:
+
+**BreakFunctionDefinitionParameters** (``Boolean``) :versionbadge:`clang-format 19` :ref:`¶ `
+ If ``true``, clang-format will always break before function definition
+ parameters.
+
+ .. code-block:: c++
+
+ true:
+ void functionDefinition(
+ int A, int B) {}
+
+ false:
+ void functionDefinition(int A, int B) {}
+
.. _BreakInheritanceList:
**BreakInheritanceList** (``BreakInheritanceListStyle``) :versionbadge:`clang-format 7` :ref:`¶ `
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 76eaf0bf11c303dc4f0b46c3ff3b75dca65f04fc..8fc925350849cd875e3fc706be77549039a1a37b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -193,6 +193,9 @@ Non-comprehensive list of changes in this release
with support for any unsigned integer type. Like the previous builtins, these
new builtins are constexpr and may be used in constant expressions.
+- ``__typeof_unqual__`` is available in all C modes as an extension, which behaves
+ like ``typeof_unqual`` from C23, similar to ``__typeof__`` and ``typeof``.
+
New Compiler Flags
------------------
@@ -253,6 +256,21 @@ Attribute Changes in Clang
added a new extension query ``__has_extension(swiftcc)`` corresponding to the
``__attribute__((swiftcc))`` attribute.
+- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply
+ to certain C++ class types, such as smart pointers:
+ ``void useObject(std::unique_ptr _Nonnull obj);``.
+
+ This works for standard library types including ``unique_ptr``, ``shared_ptr``,
+ and ``function``. See
+ `the attribute reference documentation `_
+ for the full list.
+
+- The ``_Nullable`` attribute can be applied to C++ class declarations:
+ ``template class _Nullable MySmartPointer {};``.
+
+ This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
+ apply to this class.
+
Improvements to Clang's diagnostics
-----------------------------------
- Clang now applies syntax highlighting to the code snippets it
@@ -313,6 +331,9 @@ Improvements to Clang's diagnostics
- New ``-Wformat-signedness`` diagnostic that warn if the format string requires an
unsigned argument and the argument is signed and vice versa.
+- Clang now emits ``unused argument`` warning when the -fmodule-output flag is used
+ with an input that is not of type c++-module.
+
Improvements to Clang's time-trace
----------------------------------
@@ -468,6 +489,11 @@ Bug Fixes to C++ Support
following the first `::` were ignored).
- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757).
- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).
+- Fixed a bug that prevented member function templates of class templates declared with a deduced return type
+ from being explicitly specialized for a given implicit instantiation of the class template.
+
+- Fix crash when inheriting from a cv-qualified type. Fixes:
+ (`#35603 `_)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42eeb19bdfe178889ce272c25d56..2bfefeabc348bee1cc399a43bfd8aa057a18ec3d 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3163,23 +3163,12 @@ public:
}
};
-/// Extra data stored in some MemberExpr objects.
-struct MemberExprNameQualifier {
- /// The nested-name-specifier that qualifies the name, including
- /// source-location information.
- NestedNameSpecifierLoc QualifierLoc;
-
- /// The DeclAccessPair through which the MemberDecl was found due to
- /// name qualifiers.
- DeclAccessPair FoundDecl;
-};
-
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr final
: public Expr,
- private llvm::TrailingObjects {
friend class ASTReader;
friend class ASTStmtReader;
@@ -3201,26 +3190,30 @@ class MemberExpr final
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
- size_t numTrailingObjects(OverloadToken) const {
- return hasQualifierOrFoundDecl();
+ size_t numTrailingObjects(OverloadToken) const {
+ return hasQualifier();
+ }
+
+ size_t numTrailingObjects(OverloadToken) const {
+ return hasFoundDecl();
}
size_t numTrailingObjects(OverloadToken) const {
return hasTemplateKWAndArgsInfo();
}
- bool hasQualifierOrFoundDecl() const {
- return MemberExprBits.HasQualifierOrFoundDecl;
- }
+ bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; }
bool hasTemplateKWAndArgsInfo() const {
return MemberExprBits.HasTemplateKWAndArgsInfo;
}
MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
- ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
- QualType T, ExprValueKind VK, ExprObjectKind OK,
- NonOdrUseReason NOUR);
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs, QualType T,
+ ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR);
MemberExpr(EmptyShell Empty)
: Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
@@ -3264,24 +3257,24 @@ public:
/// Retrieves the declaration found by lookup.
DeclAccessPair getFoundDecl() const {
- if (!hasQualifierOrFoundDecl())
+ if (!hasFoundDecl())
return DeclAccessPair::make(getMemberDecl(),
getMemberDecl()->getAccess());
- return getTrailingObjects()->FoundDecl;
+ return *getTrailingObjects();
}
/// Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return getQualifier() != nullptr; }
+ bool hasQualifier() const { return MemberExprBits.HasQualifier; }
/// If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
- if (!hasQualifierOrFoundDecl())
+ if (!hasQualifier())
return NestedNameSpecifierLoc();
- return getTrailingObjects()->QualifierLoc;
+ return *getTrailingObjects();
}
/// If the member name was qualified, retrieves the
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 55eca4007d17ea25c9244cf94fe34b849461149b..8892518d58e853230751cf3cf67d1eaff8258e5d 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -583,11 +583,13 @@ protected:
unsigned IsArrow : 1;
/// True if this member expression used a nested-name-specifier to
- /// refer to the member, e.g., "x->Base::f", or found its member via
- /// a using declaration. When true, a MemberExprNameQualifier
- /// structure is allocated immediately after the MemberExpr.
+ /// refer to the member, e.g., "x->Base::f".
LLVM_PREFERRED_TYPE(bool)
- unsigned HasQualifierOrFoundDecl : 1;
+ unsigned HasQualifier : 1;
+
+ // True if this member expression found its member via a using declaration.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned HasFoundDecl : 1;
/// True if this member expression specified a template keyword
/// and/or a template argument list explicitly, e.g., x->f,
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index c30bccd06674a4d9036930a386b9da4afae78418..9a65f76cdf56bcb3de4fb36bc699d904f87e2308 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -43,6 +43,15 @@ enum class ComparisonResult {
Unknown,
};
+/// The result of a `widen` operation.
+struct WidenResult {
+ /// Non-null pointer to a potentially widened version of the input value.
+ Value *V;
+ /// Whether `V` represents a "change" (that is, a different value) with
+ /// respect to the previous value in the sequence.
+ LatticeEffect Effect;
+};
+
/// Holds the state of the program (store and heap) at a given program point.
///
/// WARNING: Symbolic values that are created by the environment for static
@@ -104,14 +113,17 @@ public:
/// serve as a comparison operation, by indicating whether the widened value
/// is equivalent to the previous value.
///
- /// Returns either:
- ///
- /// `nullptr`, if this value is not of interest to the model, or
- ///
- /// `&Prev`, if the widened value is equivalent to `Prev`, or
- ///
- /// A non-null value that approximates `Current`. `Prev` is available to
- /// inform the chosen approximation.
+ /// Returns one of the folowing:
+ /// * `std::nullopt`, if this value is not of interest to the
+ /// model.
+ /// * A `WidenResult` with:
+ /// * A non-null `Value *` that points either to `Current` or a widened
+ /// version of `Current`. This value must be consistent with
+ /// the flow condition of `CurrentEnv`. We particularly caution
+ /// against using `Prev`, which is rarely consistent.
+ /// * A `LatticeEffect` indicating whether the value should be
+ /// considered a new value (`Changed`) or one *equivalent* (if not
+ /// necessarily equal) to `Prev` (`Unchanged`).
///
/// `PrevEnv` and `CurrentEnv` can be used to query child values and path
/// condition implications of `Prev` and `Current`, respectively.
@@ -122,17 +134,19 @@ public:
///
/// `Prev` and `Current` must be assigned to the same storage location in
/// `PrevEnv` and `CurrentEnv`, respectively.
- virtual Value *widen(QualType Type, Value &Prev, const Environment &PrevEnv,
- Value &Current, Environment &CurrentEnv) {
+ virtual std::optional widen(QualType Type, Value &Prev,
+ const Environment &PrevEnv,
+ Value &Current,
+ Environment &CurrentEnv) {
// The default implementation reduces to just comparison, since comparison
// is required by the API, even if no widening is performed.
switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) {
- case ComparisonResult::Same:
- return &Prev;
- case ComparisonResult::Different:
- return &Current;
- case ComparisonResult::Unknown:
- return nullptr;
+ case ComparisonResult::Unknown:
+ return std::nullopt;
+ case ComparisonResult::Same:
+ return WidenResult{&Current, LatticeEffect::Unchanged};
+ case ComparisonResult::Different:
+ return WidenResult{&Current, LatticeEffect::Changed};
}
llvm_unreachable("all cases in switch covered");
}
@@ -236,8 +250,8 @@ public:
///
/// `PrevEnv` must be the immediate previous version of the environment.
/// `PrevEnv` and `this` must use the same `DataflowAnalysisContext`.
- LatticeJoinEffect widen(const Environment &PrevEnv,
- Environment::ValueModel &Model);
+ LatticeEffect widen(const Environment &PrevEnv,
+ Environment::ValueModel &Model);
// FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`,
// `getStableStorageLocation`, or something more appropriate.
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h b/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h
index 0c81e2f078c2412a9333e0432953db6093e0cdf1..b262732804ed692436da71317c34adcc103e3485 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h
@@ -17,13 +17,13 @@
namespace clang {
namespace dataflow {
-/// Effect indicating whether a lattice join operation resulted in a new value.
-// FIXME: Rename to `LatticeEffect` since `widen` uses it as well, and we are
-// likely removing it from `join`.
-enum class LatticeJoinEffect {
+/// Effect indicating whether a lattice operation resulted in a new value.
+enum class LatticeEffect {
Unchanged,
Changed,
};
+// DEPRECATED. Use `LatticeEffect`.
+using LatticeJoinEffect = LatticeEffect;
} // namespace dataflow
} // namespace clang
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 80e607525a0a37dcdaff9f508cb222b3a402da8d..6584460cf5685ea031ab5a6f746ae10871c8caf2 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2178,9 +2178,10 @@ def TypeNonNull : TypeAttr {
let Documentation = [TypeNonNullDocs];
}
-def TypeNullable : TypeAttr {
+def TypeNullable : DeclOrTypeAttr {
let Spellings = [CustomKeyword<"_Nullable">];
let Documentation = [TypeNullableDocs];
+// let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
}
def TypeNullableResult : TypeAttr {
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 3ea4d676b4f89d30eb03a5e80419dfccfeca06e9..0ca4ea377fc36aca742d155d53edb072474ab255 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -4151,6 +4151,20 @@ non-underscored keywords. For example:
@property (assign, nullable) NSView *superview;
@property (readonly, nonnull) NSArray *subviews;
@end
+
+As well as built-in pointer types, the nullability attributes can be attached
+to C++ classes marked with the ``_Nullable`` attribute.
+
+The following C++ standard library types are considered nullable:
+``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``,
+``move_only_function`` and ``coroutine_handle``.
+
+Types should be marked nullable only where the type itself leaves nullability
+ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because
+``optional _Nullable`` is redundant and ``optional _Nonnull`` is
+not a useful type. ``std::weak_ptr`` is not nullable, because its nullability
+can change with no visible modification, so static annotation is unlikely to be
+unhelpful.
}];
}
@@ -4185,6 +4199,17 @@ The ``_Nullable`` nullability qualifier indicates that a value of the
int fetch_or_zero(int * _Nullable ptr);
a caller of ``fetch_or_zero`` can provide null.
+
+The ``_Nullable`` attribute on classes indicates that the given class can
+represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers
+make sense for this type. For example:
+
+ .. code-block:: c
+
+ class _Nullable ArenaPointer { ... };
+
+ ArenaPointer _Nonnull x = ...;
+ ArenaPointer _Nullable y = nullptr;
}];
}
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 592ed3bda51506624b0438f6fdce1ab31a7ab0b0..3d86f7510bde208f1efe03c8baee0505b3f1e8d5 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -548,6 +548,12 @@ def err_drv_extract_api_wrong_kind : Error<
"header file '%0' input '%1' does not match the type of prior input "
"in api extraction; use '-x %2' to override">;
+def err_drv_missing_symbol_graph_dir: Error<
+ "Must provide a symbol graph output directory using --symbol-graph-dir=">;
+
+def err_drv_unexpected_symbol_graph_output : Error<
+ "Unexpected output symbol graph '%1'; please provide --symbol-graph-dir= instead">;
+
def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
InGroup>;
def note_use_dashdash : Note<
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index ba23cf84c5e3438d860c0f65e5bbf472f3b63946..14b08d4927ec5e264ac9bb73cf8f07ebc4eb1cc2 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -366,4 +366,8 @@ def warn_profile_data_misexpect : Warning<
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
+def warn_missing_symbol_graph_dir : Warning<
+ "Missing symbol graph output directory, defaulting to working directory">,
+ InGroup;
+
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 520168f01fd846c540c22e958b709f9d72b2e9c1..5251774ff4efd6d7f607431511991ca633d22252 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1517,3 +1517,5 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon
// Warnings and notes InstallAPI verification.
def InstallAPIViolation : DiagGroup<"installapi-violation">;
+// Warnings about misuse of ExtractAPI options.
+def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h
index 5ff782c7f8c7e812203a77fbc91beb751e8f78d9..bce7605b95ba43f298d34b9d67c9e681424e7a74 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -32,7 +32,7 @@ namespace clang {
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
- DIAG_SIZE_FRONTEND = 150,
+ DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 400,
DIAG_SIZE_PARSE = 700,
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index b41aadc73f205d5db241bdbdd5638f76e3272cb9..fe4d1c4afcca6538ecec88e77fc08970dc9d8d5c 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -94,6 +94,7 @@ EXTENSION(define_target_os_macros,
FEATURE(enumerator_attributes, true)
FEATURE(nullability, true)
FEATURE(nullability_on_arrays, true)
+FEATURE(nullability_on_classes, true)
FEATURE(nullability_nullable_result, true)
FEATURE(memory_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 3a96f8a4d22bd14b843a9fb3a3750676255726c1..800af0e6d0448058d901d396e4f41025610d3b02 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -665,28 +665,30 @@ KEYWORD(__kindof , KEYOBJC)
// Alternate spelling for various tokens. There are GCC extensions in all
// languages, but should not be disabled in strict conformance mode.
-ALIAS("__alignof__" , __alignof , KEYALL)
-ALIAS("__asm" , asm , KEYALL)
-ALIAS("__asm__" , asm , KEYALL)
-ALIAS("__attribute__", __attribute, KEYALL)
-ALIAS("__complex" , _Complex , KEYALL)
-ALIAS("__complex__" , _Complex , KEYALL)
-ALIAS("__const" , const , KEYALL)
-ALIAS("__const__" , const , KEYALL)
-ALIAS("__decltype" , decltype , KEYCXX)
-ALIAS("__imag__" , __imag , KEYALL)
-ALIAS("__inline" , inline , KEYALL)
-ALIAS("__inline__" , inline , KEYALL)
-ALIAS("__nullptr" , nullptr , KEYCXX)
-ALIAS("__real__" , __real , KEYALL)
-ALIAS("__restrict" , restrict , KEYALL)
-ALIAS("__restrict__" , restrict , KEYALL)
-ALIAS("__signed" , signed , KEYALL)
-ALIAS("__signed__" , signed , KEYALL)
-ALIAS("__typeof" , typeof , KEYALL)
-ALIAS("__typeof__" , typeof , KEYALL)
-ALIAS("__volatile" , volatile , KEYALL)
-ALIAS("__volatile__" , volatile , KEYALL)
+ALIAS("__alignof__" , __alignof , KEYALL)
+ALIAS("__asm" , asm , KEYALL)
+ALIAS("__asm__" , asm , KEYALL)
+ALIAS("__attribute__" , __attribute , KEYALL)
+ALIAS("__complex" , _Complex , KEYALL)
+ALIAS("__complex__" , _Complex , KEYALL)
+ALIAS("__const" , const , KEYALL)
+ALIAS("__const__" , const , KEYALL)
+ALIAS("__decltype" , decltype , KEYCXX)
+ALIAS("__imag__" , __imag , KEYALL)
+ALIAS("__inline" , inline , KEYALL)
+ALIAS("__inline__" , inline , KEYALL)
+ALIAS("__nullptr" , nullptr , KEYCXX)
+ALIAS("__real__" , __real , KEYALL)
+ALIAS("__restrict" , restrict , KEYALL)
+ALIAS("__restrict__" , restrict , KEYALL)
+ALIAS("__signed" , signed , KEYALL)
+ALIAS("__signed__" , signed , KEYALL)
+ALIAS("__typeof" , typeof , KEYALL)
+ALIAS("__typeof__" , typeof , KEYALL)
+ALIAS("__typeof_unqual" , typeof_unqual, KEYALL)
+ALIAS("__typeof_unqual__", typeof_unqual, KEYALL)
+ALIAS("__volatile" , volatile , KEYALL)
+ALIAS("__volatile__" , volatile , KEYALL)
// Type nullability.
KEYWORD(_Nonnull , KEYALL)
diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td
index f16de97f4e6bdafd7b5ec43b0719f1207c0558c7..7edac5afafaa996704c89911beeb5d52c061621e 100644
--- a/clang/include/clang/Basic/arm_neon.td
+++ b/clang/include/clang/Basic/arm_neon.td
@@ -1758,24 +1758,21 @@ let TargetGuard = "fullfp16" in {
// Mul lane
def VMUL_LANEH : IOpInst<"vmul_lane", "..qI", "hQh", OP_MUL_LN>;
def VMUL_NH : IOpInst<"vmul_n", "..1", "hQh", OP_MUL_N>;
+}
- // Data processing intrinsics - section 5
-
- // Logical operations
- let isHiddenLInst = 1 in
- def VBSLH : SInst<"vbsl", ".U..", "hQh">;
-
- // Transposition operations
- def VZIPH : WInst<"vzip", "2..", "hQh">;
- def VUZPH : WInst<"vuzp", "2..", "hQh">;
- def VTRNH : WInst<"vtrn", "2..", "hQh">;
-
- // Vector Extract
- def VEXTH : WInst<"vext", "...I", "hQh">;
+// Data processing intrinsics - section 5. Do not require fullfp16.
- // Reverse vector elements
- def VREV64H : WOpInst<"vrev64", "..", "hQh", OP_REV64>;
-}
+// Logical operations
+let isHiddenLInst = 1 in
+def VBSLH : SInst<"vbsl", ".U..", "hQh">;
+// Transposition operations
+def VZIPH : WInst<"vzip", "2..", "hQh">;
+def VUZPH : WInst<"vuzp", "2..", "hQh">;
+def VTRNH : WInst<"vtrn", "2..", "hQh">;
+// Vector Extract
+def VEXTH : WInst<"vext", "...I", "hQh">;
+// Reverse vector elements
+def VREV64H : WOpInst<"vrev64", "..", "hQh", OP_REV64>;
// ARMv8.2-A FP16 vector intrinsics for A64 only.
let ArchGuard = "defined(__aarch64__)", TargetGuard = "fullfp16" in {
@@ -1857,7 +1854,9 @@ let ArchGuard = "defined(__aarch64__)", TargetGuard = "fullfp16" in {
def VMINVH : SInst<"vminv", "1.", "hQh">;
def FMAXNMVH : SInst<"vmaxnmv", "1.", "hQh">;
def FMINNMVH : SInst<"vminnmv", "1.", "hQh">;
+}
+let ArchGuard = "defined(__aarch64__)" in {
// Permutation
def VTRN1H : SOpInst<"vtrn1", "...", "hQh", OP_TRN1>;
def VZIP1H : SOpInst<"vzip1", "...", "hQh", OP_ZIP1>;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f5289fb00c895e676c43e20169ff2dffef359ab0..c3e90a70925b78d133919c3dcf21732fffdca8b9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1507,14 +1507,29 @@ def extract_api : Flag<["-"], "extract-api">,
def product_name_EQ: Joined<["--"], "product-name=">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString>;
-def emit_symbol_graph_EQ: JoinedOrSeparate<["--"], "emit-symbol-graph=">,
+def emit_symbol_graph: Flag<["-"], "emit-symbol-graph">,
Visibility<[ClangOption, CC1Option]>,
- HelpText<"Generate Extract API information as a side effect of compilation.">,
- MarshallingInfoString>;
+ HelpText<"Generate Extract API information as a side effect of compilation.">,
+ MarshallingInfoFlag>;
+def emit_extension_symbol_graphs: Flag<["--"], "emit-extension-symbol-graphs">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Generate additional symbol graphs for extended modules.">,
+ MarshallingInfoFlag>;
def extract_api_ignores_EQ: CommaJoined<["--"], "extract-api-ignores=">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Comma separated list of files containing a new line separated list of API symbols to ignore when extracting API information.">,
MarshallingInfoStringVector>;
+def symbol_graph_dir_EQ: Joined<["--"], "symbol-graph-dir=">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Directory in which to emit symbol graphs.">,
+ MarshallingInfoString>;
+def emit_pretty_sgf: Flag<["--"], "pretty-sgf">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Emit pretty printed symbol graphs">,
+ MarshallingInfoFlag>;
+def emit_sgf_symbol_labels_for_testing: Flag<["--"], "emit-sgf-symbol-labels-for-testing">,
+ Visibility<[CC1Option]>,
+ MarshallingInfoFlag>;
def e : Separate<["-"], "e">, Flags<[LinkerInput]>, Group;
def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group,
Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index b220db294101d896ae78c02be072071c9a350b02..92cacf65c7d64e585d00687d0121d071e3c6ca0d 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -20,17 +20,25 @@
#include "clang/AST/Availability.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
+#include
+#include
#include
+#include
#include
namespace clang {
@@ -149,15 +157,58 @@ public:
/// \endcode
using DocComment = std::vector;
-// Classes deriving from APIRecord need to have USR be the first constructor
-// argument. This is so that they are compatible with `addTopLevelRecord`
-// defined in API.cpp
+struct APIRecord;
+
+// This represents a reference to another symbol that might come from external
+/// sources.
+struct SymbolReference {
+ StringRef Name;
+ StringRef USR;
+
+ /// The source project/module/product of the referred symbol.
+ StringRef Source;
+
+ // A Pointer to the APIRecord for this reference if known
+ const APIRecord *Record = nullptr;
+
+ SymbolReference() = default;
+ SymbolReference(StringRef Name, StringRef USR, StringRef Source = "")
+ : Name(Name), USR(USR), Source(Source) {}
+ SymbolReference(const APIRecord *R);
+
+ /// Determine if this SymbolReference is empty.
+ ///
+ /// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
+ bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
+};
+
+class RecordContext;
+
+// Concrete classes deriving from APIRecord need to have a construct with first
+// arguments USR, and Name, in that order. This is so that they
+// are compatible with `APISet::createRecord`.
+// When adding a new kind of record don't forget to update APIRecords.inc!
/// The base representation of an API record. Holds common symbol information.
struct APIRecord {
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum RecordKind {
RK_Unknown,
+ // If adding a record context record kind here make sure to update
+ // RecordContext::classof if needed and add a RECORD_CONTEXT entry to
+ // APIRecords.inc
+ RK_FirstRecordContext,
RK_Namespace,
+ RK_Enum,
+ RK_Struct,
+ RK_Union,
+ RK_ObjCInterface,
+ RK_ObjCCategory,
+ RK_ObjCProtocol,
+ RK_CXXClass,
+ RK_ClassTemplate,
+ RK_ClassTemplateSpecialization,
+ RK_ClassTemplatePartialSpecialization,
+ RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
@@ -166,18 +217,11 @@ struct APIRecord {
RK_GlobalVariableTemplateSpecialization,
RK_GlobalVariableTemplatePartialSpecialization,
RK_EnumConstant,
- RK_Enum,
RK_StructField,
- RK_Struct,
RK_UnionField,
- RK_Union,
RK_StaticField,
RK_CXXField,
RK_CXXFieldTemplate,
- RK_CXXClass,
- RK_ClassTemplate,
- RK_ClassTemplateSpecialization,
- RK_ClassTemplatePartialSpecialization,
RK_Concept,
RK_CXXStaticMethod,
RK_CXXInstanceMethod,
@@ -190,40 +234,15 @@ struct APIRecord {
RK_ObjCIvar,
RK_ObjCClassMethod,
RK_ObjCInstanceMethod,
- RK_ObjCInterface,
- RK_ObjCCategory,
- RK_ObjCCategoryModule,
- RK_ObjCProtocol,
RK_MacroDefinition,
RK_Typedef,
};
- /// Stores information about the context of the declaration of this API.
- /// This is roughly analogous to the DeclContext hierarchy for an AST Node.
- struct HierarchyInformation {
- /// The USR of the parent API.
- StringRef ParentUSR;
- /// The name of the parent API.
- StringRef ParentName;
- /// The record kind of the parent API.
- RecordKind ParentKind = RK_Unknown;
- /// A pointer to the parent APIRecord if known.
- APIRecord *ParentRecord = nullptr;
-
- HierarchyInformation() = default;
- HierarchyInformation(StringRef ParentUSR, StringRef ParentName,
- RecordKind Kind, APIRecord *ParentRecord = nullptr)
- : ParentUSR(ParentUSR), ParentName(ParentName), ParentKind(Kind),
- ParentRecord(ParentRecord) {}
-
- bool empty() const {
- return ParentUSR.empty() && ParentName.empty() &&
- ParentKind == RK_Unknown && ParentRecord == nullptr;
- }
- };
-
StringRef USR;
StringRef Name;
+
+ SymbolReference Parent;
+
PresumedLoc Location;
AvailabilityInfo Availability;
LinkageInfo Linkage;
@@ -242,79 +261,169 @@ struct APIRecord {
/// Objective-C class/instance methods).
DeclarationFragments SubHeading;
- /// Information about the parent record of this record.
- HierarchyInformation ParentInformation;
-
/// Whether the symbol was defined in a system header.
bool IsFromSystemHeader;
+ AccessControl Access;
+
private:
const RecordKind Kind;
+ friend class RecordContext;
+ // Used to store the next child record in RecordContext. This works because
+ // APIRecords semantically only have one parent.
+ mutable APIRecord *NextInContext = nullptr;
public:
+ APIRecord *getNextInContext() const { return NextInContext; }
+
RecordKind getKind() const { return Kind; }
+ static APIRecord *castFromRecordContext(const RecordContext *Ctx);
+ static RecordContext *castToRecordContext(const APIRecord *Record);
+
APIRecord() = delete;
APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Location, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- bool IsFromSystemHeader)
- : USR(USR), Name(Name), Location(Location),
+ SymbolReference Parent, PresumedLoc Location,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader,
+ AccessControl Access = AccessControl())
+ : USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location),
Availability(std::move(Availability)), Linkage(Linkage),
Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
- IsFromSystemHeader(IsFromSystemHeader), Kind(Kind) {}
+ IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)),
+ Kind(Kind) {}
APIRecord(RecordKind Kind, StringRef USR, StringRef Name)
: USR(USR), Name(Name), Kind(Kind) {}
// Pure virtual destructor to make APIRecord abstract
virtual ~APIRecord() = 0;
+ static bool classof(const APIRecord *Record) { return true; }
+ static bool classofKind(RecordKind K) { return true; }
+ static bool classof(const RecordContext *Ctx) { return true; }
+};
+
+/// Base class used for specific record types that have children records this is
+/// analogous to the DeclContext for the AST
+class RecordContext {
+public:
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(APIRecord::RecordKind K) {
+ return K > APIRecord::RK_FirstRecordContext &&
+ K < APIRecord::RK_LastRecordContext;
+ }
+
+ static bool classof(const RecordContext *Context) { return true; }
+
+ RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}
+
+ APIRecord::RecordKind getKind() const { return Kind; }
+
+ struct record_iterator {
+ private:
+ APIRecord *Current = nullptr;
+
+ public:
+ using value_type = APIRecord *;
+ using reference = const value_type &;
+ using pointer = const value_type *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+
+ record_iterator() = default;
+ explicit record_iterator(value_type R) : Current(R) {}
+ reference operator*() const { return Current; }
+ // This doesn't strictly meet the iterator requirements, but it's the
+ // behavior we want here.
+ value_type operator->() const { return Current; }
+ record_iterator &operator++() {
+ Current = Current->getNextInContext();
+ return *this;
+ }
+ record_iterator operator++(int) {
+ record_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(record_iterator x, record_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(record_iterator x, record_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ using record_range = llvm::iterator_range;
+ record_range records() const {
+ return record_range(records_begin(), records_end());
+ }
+ record_iterator records_begin() const { return record_iterator(First); };
+ record_iterator records_end() const { return record_iterator(); }
+ bool records_empty() const { return First == nullptr; };
+
+private:
+ APIRecord::RecordKind Kind;
+ mutable APIRecord *First = nullptr;
+ mutable APIRecord *Last = nullptr;
+
+protected:
+ friend class APISet;
+ void addToRecordChain(APIRecord *) const;
};
-struct NamespaceRecord : APIRecord {
- NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
+struct NamespaceRecord : APIRecord, RecordContext {
+ NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ RecordContext(RK_Namespace) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Namespace;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_Namespace; }
};
/// This holds information associated with global functions.
struct GlobalFunctionRecord : APIRecord {
FunctionSignature Signature;
- GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : APIRecord(RK_GlobalFunction, USR, Name, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader),
+ : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc,
+ std::move(Availability), Linkage, Comment, Declaration,
+ SubHeading, IsFromSystemHeader),
Signature(Signature) {}
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, IsFromSystemHeader),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader),
Signature(Signature) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalFunction;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
private:
virtual void anchor();
@@ -323,63 +432,74 @@ private:
struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
Template Templ;
- GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ GlobalFunctionTemplateRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, Template Template,
bool IsFromSystemHeader)
- : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc,
+ : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalFunctionTemplate;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalFunctionTemplate;
}
};
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
- Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Signature,
+ Parent, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading, Signature,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalFunctionTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalFunctionTemplateSpecialization;
}
};
/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
- GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_GlobalVariable, USR, Name, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
+ std::move(Availability), Linkage, Comment, Declaration,
+ SubHeading, IsFromSystemHeader) {}
GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
+ SymbolReference Parent,
+
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, IsFromSystemHeader) {}
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariable;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
private:
virtual void anchor();
@@ -388,34 +508,42 @@ private:
struct GlobalVariableTemplateRecord : GlobalVariableRecord {
Template Templ;
- GlobalVariableTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ GlobalVariableTemplateRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
class Template Template, bool IsFromSystemHeader)
- : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Loc,
+ : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariableTemplate;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalVariableTemplate;
}
};
struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
- Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, IsFromSystemHeader) {}
+ Parent, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariableTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalVariableTemplateSpecialization;
}
};
@@ -424,126 +552,203 @@ struct GlobalVariableTemplatePartialSpecializationRecord
Template Templ;
GlobalVariableTemplatePartialSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, class Template Template,
bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
- USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading,
+ USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariableTemplatePartialSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalVariableTemplatePartialSpecialization;
}
};
/// This holds information associated with enum constants.
struct EnumConstantRecord : APIRecord {
- EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_EnumConstant, USR, Name, Loc, std::move(Availability),
- LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc,
+ std::move(Availability), LinkageInfo::none(), Comment,
+ Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_EnumConstant;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
private:
virtual void anchor();
};
/// This holds information associated with enums.
-struct EnumRecord : APIRecord {
- SmallVector> Constants;
-
- EnumRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- bool IsFromSystemHeader)
- : APIRecord(RK_Enum, USR, Name, Loc, std::move(Availability),
+struct EnumRecord : APIRecord, RecordContext {
+ EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ RecordContext(RK_Enum) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Enum;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_Enum; }
private:
virtual void anchor();
};
-/// This holds information associated with struct fields.
+/// This holds information associated with struct or union fields fields.
struct RecordFieldRecord : APIRecord {
- RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
- DeclarationFragments SubHeading, RecordKind Kind,
- bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_StructField ||
- Record->getKind() == RK_UnionField;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_StructField || K == RK_UnionField;
}
-private:
- virtual void anchor();
+ virtual ~RecordFieldRecord() = 0;
};
-/// This holds information associated with structs.
-struct RecordRecord : APIRecord {
- SmallVector> Fields;
-
- RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+/// This holds information associated with structs and unions.
+struct RecordRecord : APIRecord, RecordContext {
+ RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
- DeclarationFragments SubHeading, RecordKind Kind,
- bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Struct || Record->getKind() == RK_Union;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_Struct || K == RK_Union;
}
+ virtual ~RecordRecord() = 0;
+};
+
+struct StructFieldRecord : RecordFieldRecord {
+ StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, IsFromSystemHeader) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_StructField; }
+
private:
virtual void anchor();
};
-struct CXXFieldRecord : APIRecord {
- AccessControl Access;
+struct StructRecord : RecordRecord {
+ StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
+ Comment, Declaration, SubHeading, IsFromSystemHeader) {}
- CXXFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_Struct; }
+
+private:
+ virtual void anchor();
+};
+
+struct UnionFieldRecord : RecordFieldRecord {
+ UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, IsFromSystemHeader) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_UnionField; }
+
+private:
+ virtual void anchor();
+};
+
+struct UnionRecord : RecordRecord {
+ UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
+ Comment, Declaration, SubHeading, IsFromSystemHeader) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_Union; }
+
+private:
+ virtual void anchor();
+};
+
+struct CXXFieldRecord : APIRecord {
+ CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
- : APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader, std::move(Access)) {}
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader, std::move(Access)) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXField;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
}
private:
@@ -553,111 +758,122 @@ private:
struct CXXFieldTemplateRecord : CXXFieldRecord {
Template Templ;
- CXXFieldTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
Template Template, bool IsFromSystemHeader)
- : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Loc,
+ : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Access, IsFromSystemHeader),
+ SubHeading, std::move(Access), IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXFieldTemplate;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; }
};
struct CXXMethodRecord : APIRecord {
FunctionSignature Signature;
- AccessControl Access;
CXXMethodRecord() = delete;
CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Signature(Signature), Access(Access) {}
+ IsFromSystemHeader, std::move(Access)),
+ Signature(Signature) {}
virtual ~CXXMethodRecord() = 0;
};
struct CXXConstructorRecord : CXXMethodRecord {
- CXXConstructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXConstructorMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
private:
virtual void anchor();
};
struct CXXDestructorRecord : CXXMethodRecord {
- CXXDestructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXDestructorMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
private:
virtual void anchor();
};
struct CXXStaticMethodRecord : CXXMethodRecord {
- CXXStaticMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXStaticMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
private:
virtual void anchor();
};
struct CXXInstanceMethodRecord : CXXMethodRecord {
- CXXInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXInstanceMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
private:
virtual void anchor();
@@ -666,36 +882,42 @@ private:
struct CXXMethodTemplateRecord : CXXMethodRecord {
Template Templ;
- CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
Template Template, bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader),
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXMethodTemplate;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
};
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent,
+ Loc, std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXMethodTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_CXXMethodTemplateSpecialization;
}
};
@@ -714,13 +936,13 @@ struct ObjCPropertyRecord : APIRecord {
bool IsOptional;
ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AttributeKind Attributes,
StringRef GetterName, StringRef SetterName,
bool IsOptional, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
@@ -733,44 +955,44 @@ struct ObjCPropertyRecord : APIRecord {
};
struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
- ObjCInstancePropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- AttributeKind Attributes, StringRef GetterName,
- StringRef SetterName, bool IsOptional,
- bool IsFromSystemHeader)
- : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Loc,
+ ObjCInstancePropertyRecord(
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ AttributeKind Attributes, StringRef GetterName, StringRef SetterName,
+ bool IsOptional, bool IsFromSystemHeader)
+ : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCInstanceProperty;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
private:
virtual void anchor();
};
struct ObjCClassPropertyRecord : ObjCPropertyRecord {
- ObjCClassPropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
AttributeKind Attributes, StringRef GetterName,
StringRef SetterName, bool IsOptional,
bool IsFromSystemHeader)
- : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Loc,
+ : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCClassProperty;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
private:
virtual void anchor();
@@ -778,23 +1000,21 @@ private:
/// This holds information associated with Objective-C instance variables.
struct ObjCInstanceVariableRecord : APIRecord {
- using AccessControl = ObjCIvarDecl::AccessControl;
- AccessControl Access;
-
- ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ ObjCInstanceVariableRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(RK_ObjCIvar, USR, Name, Loc, std::move(Availability),
+ bool IsFromSystemHeader)
+ : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCIvar;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
private:
virtual void anchor();
@@ -807,11 +1027,12 @@ struct ObjCMethodRecord : APIRecord {
ObjCMethodRecord() = delete;
ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
@@ -820,122 +1041,103 @@ struct ObjCMethodRecord : APIRecord {
};
struct ObjCInstanceMethodRecord : ObjCMethodRecord {
- ObjCInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ ObjCInstanceMethodRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Loc,
+ : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCInstanceMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
private:
virtual void anchor();
};
struct ObjCClassMethodRecord : ObjCMethodRecord {
- ObjCClassMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Loc,
+ : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCClassMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; }
private:
virtual void anchor();
};
-/// This represents a reference to another symbol that might come from external
-/// sources.
-struct SymbolReference {
- StringRef Name;
- StringRef USR;
-
- /// The source project/module/product of the referred symbol.
- StringRef Source;
-
- SymbolReference() = default;
- SymbolReference(StringRef Name, StringRef USR = "", StringRef Source = "")
- : Name(Name), USR(USR), Source(Source) {}
- SymbolReference(const APIRecord &Record)
- : Name(Record.Name), USR(Record.USR) {}
- SymbolReference(const APIRecord *Record)
- : Name(Record->Name), USR(Record->USR) {}
-
- /// Determine if this SymbolReference is empty.
- ///
- /// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
- bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
-};
-
struct StaticFieldRecord : CXXFieldRecord {
- SymbolReference Context;
-
- StaticFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Context,
- AccessControl Access, bool IsFromSystemHeader)
- : CXXFieldRecord(RK_StaticField, USR, Name, Loc, std::move(Availability),
- Comment, Declaration, SubHeading, Access,
- IsFromSystemHeader),
- Context(Context) {}
+ StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, AccessControl Access,
+ bool IsFromSystemHeader)
+ : CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, std::move(Access), IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_StaticField;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_StaticField; }
};
/// The base representation of an Objective-C container record. Holds common
/// information associated with Objective-C containers.
-struct ObjCContainerRecord : APIRecord {
- SmallVector> Methods;
- SmallVector> Properties;
- SmallVector> Ivars;
+struct ObjCContainerRecord : APIRecord, RecordContext {
SmallVector Protocols;
ObjCContainerRecord() = delete;
ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, IsFromSystemHeader) {}
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader),
+ RecordContext(Kind) {}
virtual ~ObjCContainerRecord() = 0;
};
-struct CXXClassRecord : APIRecord {
- SmallVector> Fields;
- SmallVector> Methods;
+struct CXXClassRecord : APIRecord, RecordContext {
SmallVector Bases;
- AccessControl Access;
- CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader, std::move(Access)),
+ RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
- return (Record->getKind() == RK_CXXClass);
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_CXXClass || K == RK_ClassTemplate ||
+ K == RK_ClassTemplateSpecialization ||
+ K == RK_ClassTemplatePartialSpecialization;
}
private:
@@ -945,86 +1147,108 @@ private:
struct ClassTemplateRecord : CXXClassRecord {
Template Templ;
- ClassTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, RK_ClassTemplate, Access,
- IsFromSystemHeader),
+ : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading, RK_ClassTemplate,
+ std::move(Access), IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ClassTemplate;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
};
struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
+ : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplateSpecialization,
Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ClassTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_ClassTemplateSpecialization;
}
};
struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
Template Templ;
ClassTemplatePartialSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, RK_ClassTemplateSpecialization,
- Access, IsFromSystemHeader),
+ : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading,
+ RK_ClassTemplatePartialSpecialization, Access,
+ IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ClassTemplatePartialSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_ClassTemplatePartialSpecialization;
}
};
struct ConceptRecord : APIRecord {
Template Templ;
- ConceptRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader)
- : APIRecord(RK_Concept, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_Concept; }
};
/// This holds information associated with Objective-C categories.
struct ObjCCategoryRecord : ObjCContainerRecord {
SymbolReference Interface;
- /// Determine whether the Category is derived from external class interface.
- bool IsFromExternalModule = false;
- ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface,
bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc,
+ : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader),
Interface(Interface) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCCategory;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; }
+
+ bool isExtendingExternalModule() const { return !Interface.Source.empty(); }
+
+ std::optional getExtendedExternalModule() const {
+ if (!isExtendingExternalModule())
+ return {};
+ return Interface.Source;
}
private:
@@ -1034,23 +1258,22 @@ private:
/// This holds information associated with Objective-C interfaces/classes.
struct ObjCInterfaceRecord : ObjCContainerRecord {
SymbolReference SuperClass;
- // ObjCCategoryRecord%s are stored in and owned by APISet.
- SmallVector Categories;
- ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass, bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc,
+ : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
SuperClass(SuperClass) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCInterface;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
private:
virtual void anchor();
@@ -1058,18 +1281,20 @@ private:
/// This holds information associated with Objective-C protocols.
struct ObjCProtocolRecord : ObjCContainerRecord {
- ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc,
+ : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCProtocol;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
private:
virtual void anchor();
@@ -1077,17 +1302,18 @@ private:
/// This holds information associated with macro definitions.
struct MacroDefinitionRecord : APIRecord {
- MacroDefinitionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- DeclarationFragments Declaration,
+ MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader)
- : APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(),
- LinkageInfo(), {}, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc,
+ AvailabilityInfo(), LinkageInfo(), {}, Declaration,
+ SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_MacroDefinition;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
private:
virtual void anchor();
@@ -1101,575 +1327,228 @@ private:
struct TypedefRecord : APIRecord {
SymbolReference UnderlyingType;
- TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference UnderlyingType,
bool IsFromSystemHeader)
- : APIRecord(RK_Typedef, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
UnderlyingType(UnderlyingType) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Typedef;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_Typedef; }
private:
virtual void anchor();
};
-/// Check if a record type has a function signature mixin.
-///
-/// This is denoted by the record type having a ``Signature`` field of type
-/// FunctionSignature.
-template
-struct has_function_signature : public std::false_type {};
-template <>
-struct has_function_signature : public std::true_type {};
-template <>
-struct has_function_signature : public std::true_type {};
-template <>
-struct has_function_signature
- : public std::true_type {};
-template <>
-struct has_function_signature : public std::true_type {};
-template <>
-struct has_function_signature : public std::true_type {};
-template <>
-struct has_function_signature : public std::true_type {};
-template <>
-struct has_function_signature : public std::true_type {
-};
-template <>
-struct has_function_signature
- : public std::true_type {};
-
-template struct has_access : public std::false_type {};
-template <> struct has_access : public std::true_type {};
-template <> struct has_access : public std::true_type {};
-template <> struct has_access : public std::true_type {};
-template <>
-struct has_access : public std::true_type {};
-template <>
-struct has_access
- : public std::true_type {};
-template <>
-struct has_access : public std::true_type {};
-template <> struct has_access : public std::true_type {};
-template <> struct has_access : public std::true_type {};
-template <>
-struct has_access : public std::true_type {};
-template <>
-struct has_access
- : public std::true_type {};
-
-template struct has_template : public std::false_type {};
-template <> struct has_template : public std::true_type {};
-template <>
-struct has_template
- : public std::true_type {};
-template <> struct has_template : public std::true_type {};
-template <>
-struct has_template : public std::true_type {};
-template <>
-struct has_template
- : public std::true_type {};
-template <>
-struct has_template : public std::true_type {};
-template <>
-struct has_template : public std::true_type {};
-
-template <>
-struct has_template : public std::true_type {};
-template <>
-struct has_function_signature
- : public std::true_type {};
-template <>
-struct has_function_signature
- : public std::true_type {};
-
/// APISet holds the set of API records collected from given inputs.
class APISet {
public:
- NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeaderg);
- /// Create and add a global variable record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- GlobalVariableRecord *
- addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeadin, bool IsFromSystemHeaderg);
+ /// Get the target triple for the ExtractAPI invocation.
+ const llvm::Triple &getTarget() const { return Target; }
- GlobalVariableTemplateRecord *
- addGlobalVariableTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader);
+ /// Get the language used by the APIs.
+ Language getLanguage() const { return Lang; }
- /// Create and add a function record into the API set.
+ /// Finds the APIRecord for a given USR.
///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- GlobalFunctionRecord *
- addGlobalFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsFromSystemHeader);
-
- GlobalFunctionTemplateRecord *addGlobalFunctionTemplate(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- Template Template, bool IsFromSystemHeader);
-
- GlobalFunctionTemplateSpecializationRecord *
- addGlobalFunctionTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader);
+ /// \returns a pointer to the APIRecord associated with that USR or nullptr.
+ APIRecord *findRecordForUSR(StringRef USR) const;
- /// Create and add an enum constant record into the API set.
+ /// Copy \p String into the Allocator in this APISet.
///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- EnumConstantRecord *
- addEnumConstant(EnumRecord *Enum, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
+ /// \returns a StringRef of the copied string in APISet::Allocator.
+ StringRef copyString(StringRef String);
- /// Create and add an enum record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
+ SymbolReference createSymbolReference(StringRef Name, StringRef USR,
+ StringRef Source = "");
- /// Create and add a record field record into the API set.
+ /// Create a subclass of \p APIRecord and store it in the APISet.
///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- RecordFieldRecord *
- addRecordField(RecordRecord *Record, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
- bool IsFromSystemHeader);
-
- /// Create and add a record record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- RecordRecord *addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind, bool IsFromSystemHeader);
-
- StaticFieldRecord *
- addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Context,
- AccessControl Access, bool IsFromSystemHeaderg);
-
- CXXFieldRecord *addCXXField(APIRecord *CXXClass, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader);
-
- CXXFieldTemplateRecord *addCXXFieldTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, Template Template, bool IsFromSystemHeader);
-
- CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind, AccessControl Access,
- bool IsFromSystemHeader);
-
- ClassTemplateRecord *
- addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- AccessControl Access, bool IsFromSystemHeader);
-
- ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader);
-
- ClassTemplatePartialSpecializationRecord *
- addClassTemplatePartialSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- Template Template, AccessControl Access, bool IsFromSystemHeader);
-
- GlobalVariableTemplateSpecializationRecord *
- addGlobalVariableTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
-
- GlobalVariableTemplatePartialSpecializationRecord *
- addGlobalVariableTemplatePartialSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader);
-
- CXXMethodRecord *addCXXInstanceMethod(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
-
- CXXMethodRecord *addCXXStaticMethod(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
-
- CXXMethodRecord *addCXXSpecialMethod(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
-
- CXXMethodTemplateRecord *addCXXMethodTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access, Template Template,
- bool IsFromSystemHeader);
+ /// \returns A pointer to the created record or the already existing record
+ /// matching this USR.
+ template
+ typename std::enable_if_t, RecordTy> *
+ createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
+
+ ArrayRef getTopLevelRecords() const {
+ return TopLevelRecords;
+ }
- CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
+ APISet(const llvm::Triple &Target, Language Lang,
+ const std::string &ProductName)
+ : Target(Target), Lang(Lang), ProductName(ProductName) {}
- ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader);
+ // Prevent moves and copies
+ APISet(const APISet &Other) = delete;
+ APISet &operator=(const APISet &Other) = delete;
+ APISet(APISet &&Other) = delete;
+ APISet &operator=(APISet &&Other) = delete;
- /// Create and add an Objective-C category record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- ObjCCategoryRecord *
- addObjCCategory(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Interface,
- bool IsFromSystemHeader, bool IsFromExternalModule);
+private:
+ /// BumpPtrAllocator that serves as the memory arena for the allocated objects
+ llvm::BumpPtrAllocator Allocator;
- /// Create and add an Objective-C interface record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- ObjCInterfaceRecord *
- addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference SuperClass,
- bool IsFromSystemHeader);
+ const llvm::Triple Target;
+ const Language Lang;
- /// Create and add an Objective-C method record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- ObjCMethodRecord *
- addObjCMethod(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsInstanceMethod, bool IsFromSystemHeader);
+ struct APIRecordDeleter {
+ void operator()(APIRecord *Record) { Record->~APIRecord(); }
+ };
- /// Create and add an Objective-C property record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- ObjCPropertyRecord *
- addObjCProperty(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- ObjCPropertyRecord::AttributeKind Attributes,
- StringRef GetterName, StringRef SetterName, bool IsOptional,
- bool IsInstanceProperty, bool IsFromSystemHeader);
+ // Ensure that the destructor of each record is called when the LookupTable is
+ // destroyed without calling delete operator as the memory for the record
+ // lives in the BumpPtrAllocator.
+ using APIRecordStoredPtr = std::unique_ptr;
+ llvm::DenseMap USRBasedLookupTable;
+ std::vector TopLevelRecords;
- /// Create and add an Objective-C instance variable record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- ObjCInstanceVariableRecord *addObjCInstanceVariable(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCInstanceVariableRecord::AccessControl Access,
- bool IsFromSystemHeader);
+public:
+ const std::string ProductName;
+};
- /// Create and add an Objective-C protocol record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- ObjCProtocolRecord *
- addObjCProtocol(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
+template
+typename std::enable_if_t, RecordTy> *
+APISet::createRecord(StringRef USR, StringRef Name,
+ CtorArgsContTy &&...CtorArgs) {
+ // Ensure USR refers to a String stored in the allocator.
+ auto USRString = copyString(USR);
+ auto Result = USRBasedLookupTable.insert({USRString, nullptr});
+ RecordTy *Record;
+
+ // Create the record if it does not already exist
+ if (Result.second) {
+ Record = new (Allocator) RecordTy(
+ USRString, copyString(Name), std::forward(CtorArgs)...);
+ // Store the record in the record lookup map
+ Result.first->second = APIRecordStoredPtr(Record);
+
+ if (auto *ParentContext =
+ dyn_cast_if_present(Record->Parent.Record))
+ ParentContext->addToRecordChain(Record);
+ else
+ TopLevelRecords.push_back(Record);
+ } else {
+ Record = dyn_cast(Result.first->second.get());
+ }
- /// Create a macro definition record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSRForMacro(StringRef Name,
- /// SourceLocation SL, const SourceManager &SM) is a helper method to generate
- /// the USR for the macro and keep it alive in APISet.
- MacroDefinitionRecord *addMacroDefinition(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader);
-
- /// Create a typedef record into the API set.
- ///
- /// Note: the caller is responsible for keeping the StringRef \p Name and
- /// \p USR alive. APISet::copyString provides a way to copy strings into
- /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
- /// to generate the USR for \c D and keep it alive in APISet.
- TypedefRecord *
- addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- SymbolReference UnderlyingType, bool IsFromSystemHeader);
-
- /// A mapping type to store a set of APIRecord%s with the USR as the key.
- template ::value>>
- using RecordMap = llvm::MapVector>;
+ return Record;
+}
- /// Get the target triple for the ExtractAPI invocation.
- const llvm::Triple &getTarget() const { return Target; }
+// Helper type for implementing casting to RecordContext pointers.
+// Selected when FromTy not a known subclass of RecordContext.
+template >
+struct ToRecordContextCastInfoWrapper {
+ static_assert(std::is_base_of_v,
+ "Can only cast APIRecord and derived classes to RecordContext");
- /// Get the language used by the APIs.
- Language getLanguage() const { return Lang; }
+ static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
- const RecordMap &getNamespaces() const { return Namespaces; }
- const RecordMap &getGlobalFunctions() const {
- return GlobalFunctions;
- }
- const RecordMap &
- getGlobalFunctionTemplates() const {
- return GlobalFunctionTemplates;
- }
- const RecordMap &
- getGlobalFunctionTemplateSpecializations() const {
- return GlobalFunctionTemplateSpecializations;
- }
- const RecordMap &getGlobalVariables() const {
- return GlobalVariables;
- }
- const RecordMap &
- getGlobalVariableTemplates() const {
- return GlobalVariableTemplates;
+ static RecordContext *doCast(FromTy *From) {
+ return APIRecord::castToRecordContext(From);
}
- const RecordMap &getStaticFields() const {
- return StaticFields;
- }
- const RecordMap &
- getGlobalVariableTemplateSpecializations() const {
- return GlobalVariableTemplateSpecializations;
- }
- const RecordMap &
- getGlobalVariableTemplatePartialSpecializations() const {
- return GlobalVariableTemplatePartialSpecializations;
- }
- const RecordMap &getEnums() const { return Enums; }
- const RecordMap &getRecords() const { return Records; }
- const RecordMap &getCXXClasses() const { return CXXClasses; }
- const RecordMap &getCXXMethodTemplates() const {
- return CXXMethodTemplates;
- }
- const RecordMap &getCXXInstanceMethods() const {
- return CXXInstanceMethods;
- }
- const RecordMap &getCXXStaticMethods() const {
- return CXXStaticMethods;
- }
- const RecordMap &getCXXFields() const { return CXXFields; }
- const RecordMap &
- getCXXMethodTemplateSpecializations() const {
- return CXXMethodTemplateSpecializations;
- }
- const RecordMap &getCXXFieldTemplates() const {
- return CXXFieldTemplates;
- }
- const RecordMap &getClassTemplates() const {
- return ClassTemplates;
- }
- const RecordMap &
- getClassTemplateSpecializations() const {
- return ClassTemplateSpecializations;
+};
+
+// Selected when FromTy is a known subclass of RecordContext.
+template struct ToRecordContextCastInfoWrapper {
+ static_assert(std::is_base_of_v,
+ "Can only cast APIRecord and derived classes to RecordContext");
+ static bool isPossible(const FromTy *From) { return true; }
+ static RecordContext *doCast(FromTy *From) {
+ return static_cast(From);
}
- const RecordMap &
- getClassTemplatePartialSpecializations() const {
- return ClassTemplatePartialSpecializations;
+};
+
+// Helper type for implementing casting to RecordContext pointers.
+// Selected when ToTy isn't a known subclass of RecordContext
+template >
+struct FromRecordContextCastInfoWrapper {
+ static_assert(
+ std::is_base_of_v,
+ "Can only class RecordContext to APIRecord and derived classes");
+
+ static bool isPossible(RecordContext *Ctx) {
+ return ToTy::classofKind(Ctx->getKind());
}
- const RecordMap &getConcepts() const { return Concepts; }
- const RecordMap &getObjCCategories() const {
- return ObjCCategories;
+
+ static ToTy *doCast(RecordContext *Ctx) {
+ return APIRecord::castFromRecordContext(Ctx);
}
- const RecordMap &getObjCInterfaces() const {
- return ObjCInterfaces;
+};
+
+// Selected when ToTy is a known subclass of RecordContext.
+template struct FromRecordContextCastInfoWrapper {
+ static_assert(
+ std::is_base_of_v,
+ "Can only class RecordContext to APIRecord and derived classes");
+ static bool isPossible(RecordContext *Ctx) {
+ return ToTy::classof(Ctx->getKind());
}
- const RecordMap &getObjCProtocols() const {
- return ObjCProtocols;
+ static RecordContext *doCast(RecordContext *Ctx) {
+ return static_cast(Ctx);
}
- const RecordMap &getMacros() const { return Macros; }
- const RecordMap &getTypedefs() const { return Typedefs; }
-
- /// Finds the APIRecord for a given USR.
- ///
- /// \returns a pointer to the APIRecord associated with that USR or nullptr.
- APIRecord *findRecordForUSR(StringRef USR) const;
-
- /// Generate and store the USR of declaration \p D.
- ///
- /// Note: The USR string is stored in and owned by Allocator.
- ///
- /// \returns a StringRef of the generated USR string.
- StringRef recordUSR(const Decl *D);
-
- /// Generate and store the USR for a macro \p Name.
- ///
- /// Note: The USR string is stored in and owned by Allocator.
- ///
- /// \returns a StringRef to the generate USR string.
- StringRef recordUSRForMacro(StringRef Name, SourceLocation SL,
- const SourceManager &SM);
-
- /// Copy \p String into the Allocator in this APISet.
- ///
- /// \returns a StringRef of the copied string in APISet::Allocator.
- StringRef copyString(StringRef String);
+};
- APISet(const llvm::Triple &Target, Language Lang,
- const std::string &ProductName)
- : Target(Target), Lang(Lang), ProductName(ProductName) {}
+} // namespace extractapi
+} // namespace clang
-private:
- /// BumpPtrAllocator to store generated/copied strings.
- ///
- /// Note: The main use for this is being able to deduplicate strings.
- llvm::BumpPtrAllocator StringAllocator;
+// Implement APIRecord (and derived classes) to and from RecordContext
+// conversions
+namespace llvm {
+
+template
+struct CastInfo<::clang::extractapi::RecordContext, FromTy *>
+ : public NullableValueCastFailed<::clang::extractapi::RecordContext *>,
+ public DefaultDoCastIfPossible<
+ ::clang::extractapi::RecordContext *, FromTy *,
+ CastInfo<::clang::extractapi::RecordContext, FromTy *>> {
+ static inline bool isPossible(FromTy *From) {
+ return ::clang::extractapi::ToRecordContextCastInfoWrapper<
+ FromTy>::isPossible(From);
+ }
- const llvm::Triple Target;
- const Language Lang;
+ static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) {
+ return ::clang::extractapi::ToRecordContextCastInfoWrapper::doCast(
+ From);
+ }
+};
- llvm::DenseMap USRBasedLookupTable;
- RecordMap Namespaces;
- RecordMap GlobalFunctions;
- RecordMap GlobalFunctionTemplates;
- RecordMap
- GlobalFunctionTemplateSpecializations;
- RecordMap GlobalVariables;
- RecordMap GlobalVariableTemplates;
- RecordMap
- GlobalVariableTemplateSpecializations;
- RecordMap
- GlobalVariableTemplatePartialSpecializations;
- RecordMap Concepts;
- RecordMap StaticFields;
- RecordMap Enums;
- RecordMap Records;
- RecordMap CXXClasses;
- RecordMap CXXFields;
- RecordMap CXXMethods;
- RecordMap CXXInstanceMethods;
- RecordMap CXXStaticMethods;
- RecordMap CXXMethodTemplates;
- RecordMap
- CXXMethodTemplateSpecializations;
- RecordMap CXXFieldTemplates;
- RecordMap ClassTemplates;
- RecordMap ClassTemplateSpecializations;
- RecordMap
- ClassTemplatePartialSpecializations;
- RecordMap ObjCCategories;
- RecordMap ObjCInterfaces;
- RecordMap ObjCProtocols;
- RecordMap Macros;
- RecordMap Typedefs;
+template
+struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
+ : public ConstStrippingForwardingCast<
+ ::clang::extractapi::RecordContext, const FromTy *,
+ CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
+
+template
+struct CastInfo
+ : public NullableValueCastFailed,
+ public DefaultDoCastIfPossible<
+ ToTy *, ::clang::extractapi::RecordContext *,
+ CastInfo> {
+ static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) {
+ return ::clang::extractapi::FromRecordContextCastInfoWrapper<
+ ToTy>::isPossible(Ctx);
+ }
-public:
- const std::string ProductName;
+ static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) {
+ return ::clang::extractapi::FromRecordContextCastInfoWrapper::doCast(
+ Ctx);
+ }
};
-} // namespace extractapi
-} // namespace clang
+template
+struct CastInfo
+ : public ConstStrippingForwardingCast<
+ ToTy, const ::clang::extractapi::RecordContext *,
+ CastInfo> {};
+
+} // namespace llvm
#endif // LLVM_CLANG_EXTRACTAPI_API_H
diff --git a/clang/include/clang/ExtractAPI/APIRecords.inc b/clang/include/clang/ExtractAPI/APIRecords.inc
new file mode 100644
index 0000000000000000000000000000000000000000..15fee809656d9a4b5e50ba7b1f8c2ff88978128e
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/APIRecords.inc
@@ -0,0 +1,103 @@
+//===- ExtractAPI/APIRecords.inc --------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the classes defined from ExtractAPI's APIRecord
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ABSTRACT_RECORD
+#define ABSTRACT_RECORD(CLASS, BASE) RECORD(CLASS, BASE)
+#endif
+#ifndef CONCRETE_RECORD
+#define CONCRETE_RECORD(CLASS, BASE, KIND) RECORD(CLASS, BASE)
+#endif
+#ifndef RECORD
+#define RECORD(CLASS, BASE)
+#endif
+
+CONCRETE_RECORD(NamespaceRecord, APIRecord, RK_Namespace)
+CONCRETE_RECORD(GlobalFunctionRecord, APIRecord, RK_GlobalFunction)
+CONCRETE_RECORD(GlobalFunctionTemplateRecord, GlobalFunctionRecord,
+ RK_GlobalFunctionTemplate)
+CONCRETE_RECORD(GlobalFunctionTemplateSpecializationRecord,
+ GlobalFunctionRecord, RK_GlobalFunctionTemplateSpecialization)
+CONCRETE_RECORD(GlobalVariableRecord, APIRecord, RK_GlobalVariable)
+CONCRETE_RECORD(GlobalVariableTemplateRecord, GlobalVariableRecord,
+ RK_GlobalVariableTemplate)
+CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
+ GlobalVariableRecord, RK_GlobalVariableTemplateSpecialization)
+CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
+ GlobalVariableRecord,
+ RK_GlobalVariableTemplatePartialSpecialization)
+CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
+CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
+ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
+ABSTRACT_RECORD(RecordRecord, APIRecord)
+CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
+CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
+CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
+CONCRETE_RECORD(UnionRecord, APIRecord, RK_Union)
+CONCRETE_RECORD(CXXFieldRecord, APIRecord, RK_CXXField)
+CONCRETE_RECORD(CXXFieldTemplateRecord, CXXFieldRecord, RK_CXXFieldTemplate)
+ABSTRACT_RECORD(CXXMethodRecord, APIRecord)
+CONCRETE_RECORD(CXXConstructorRecord, CXXMethodRecord, RK_CXXConstructorMethod)
+CONCRETE_RECORD(CXXDestructorRecord, CXXMethodRecord, RK_CXXDestructorMethod)
+CONCRETE_RECORD(CXXStaticMethodRecord, CXXMethodRecord, RK_CXXStaticMethod)
+CONCRETE_RECORD(CXXInstanceMethodRecord, CXXMethodRecord, RK_CXXInstanceMethod)
+CONCRETE_RECORD(CXXMethodTemplateRecord, CXXMethodRecord, RK_CXXMethodTemplate)
+CONCRETE_RECORD(CXXMethodTemplateSpecializationRecord, CXXMethodRecord,
+ RK_CXXMethodTemplateSpecialization)
+ABSTRACT_RECORD(ObjCPropertyRecord, APIRecord)
+CONCRETE_RECORD(ObjCInstancePropertyRecord, ObjCPropertyRecord,
+ RK_ObjCInstanceProperty)
+CONCRETE_RECORD(ObjCClassPropertyRecord, ObjCPropertyRecord,
+ RK_ObjCClassProperty)
+CONCRETE_RECORD(ObjCInstanceVariableRecord, APIRecord, RK_ObjCIvar)
+ABSTRACT_RECORD(ObjCMethodRecord, APIRecord)
+CONCRETE_RECORD(ObjCInstanceMethodRecord, ObjCMethodRecord,
+ RK_ObjCInstanceMethod)
+CONCRETE_RECORD(ObjCClassMethodRecord, ObjCMethodRecord, RK_ObjCClassMethod)
+CONCRETE_RECORD(StaticFieldRecord, CXXFieldRecord, RK_StaticField)
+ABSTRACT_RECORD(ObjCContainerRecord, APIRecord)
+CONCRETE_RECORD(CXXClassRecord, APIRecord, RK_CXXClass)
+CONCRETE_RECORD(ClassTemplateRecord, CXXClassRecord, RK_ClassTemplate)
+CONCRETE_RECORD(ClassTemplateSpecializationRecord, CXXClassRecord,
+ RK_ClassTemplateSpecialization)
+CONCRETE_RECORD(ClassTemplatePartialSpecializationRecord, CXXClassRecord,
+ RK_ClassTemplatePartialSpecialization)
+CONCRETE_RECORD(ConceptRecord, APIRecord, RK_Concept)
+CONCRETE_RECORD(ObjCCategoryRecord, ObjCContainerRecord, RK_ObjCCategory)
+CONCRETE_RECORD(ObjCInterfaceRecord, ObjCContainerRecord, RK_ObjCInterface)
+CONCRETE_RECORD(ObjCProtocolRecord, ObjCContainerRecord, RK_ObjCProtocol)
+CONCRETE_RECORD(MacroDefinitionRecord, APIRecord, RK_MacroDefinition)
+CONCRETE_RECORD(TypedefRecord, APIRecord, RK_Typedef)
+
+#undef CONCRETE_RECORD
+#undef ABSTRACT_RECORD
+#undef RECORD
+
+#ifndef RECORD_CONTEXT
+#define RECORD_CONTEXT(CLASS, KIND)
+#endif
+
+RECORD_CONTEXT(NamespaceRecord, RK_Namespace)
+RECORD_CONTEXT(EnumRecord, RK_Enum)
+RECORD_CONTEXT(StructRecord, RK_Struct)
+RECORD_CONTEXT(UnionRecord, RK_Union)
+RECORD_CONTEXT(ObjCCategoryRecord, RK_ObjCCategory)
+RECORD_CONTEXT(ObjCInterfaceRecord, RK_ObjCInterface)
+RECORD_CONTEXT(ObjCProtocolRecord, RK_ObjCProtocol)
+RECORD_CONTEXT(CXXClassRecord, RK_CXXClass)
+RECORD_CONTEXT(ClassTemplateRecord, RK_ClassTemplate)
+RECORD_CONTEXT(ClassTemplateSpecializationRecord,
+ RK_ClassTemplateSpecialization)
+RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
+ RK_ClassTemplatePartialSpecialization)
+
+#undef RECORD_CONTEXT
diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
index b85a5d21d61217e2404c7c54bde6ed5f5d2f34e2..94392c185165951c39adad41cd402f83cd30119c 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -27,8 +27,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/MacroInfo.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include
namespace clang {
@@ -182,6 +180,18 @@ public:
/// appending to chain up consecutive appends.
DeclarationFragments &appendSpace();
+ /// Append a text Fragment of a semicolon character.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// appending to chain up consecutive appends.
+ DeclarationFragments &appendSemicolon();
+
+ /// Removes a trailing semicolon character if present.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// removing to chain up consecutive operations.
+ DeclarationFragments &removeTrailingSemicolon();
+
/// Get the string description of a FragmentKind \p Kind.
static StringRef getFragmentKindString(FragmentKind Kind);
@@ -194,12 +204,14 @@ public:
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
private:
+ DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
std::vector Fragments;
};
class AccessControl {
public:
AccessControl(std::string Access) : Access(Access) {}
+ AccessControl() : Access("public") {}
const std::string &getAccess() const { return Access; }
@@ -315,13 +327,9 @@ public:
static DeclarationFragments
getFragmentsForTemplateParameters(ArrayRef);
- static std::string
- getNameForTemplateArgument(const ArrayRef, std::string);
-
- static DeclarationFragments
- getFragmentsForTemplateArguments(const ArrayRef,
- ASTContext &,
- const std::optional>);
+ static DeclarationFragments getFragmentsForTemplateArguments(
+ const ArrayRef, ASTContext &,
+ const std::optional>);
static DeclarationFragments getFragmentsForConcept(const ConceptDecl *);
@@ -430,12 +438,7 @@ DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
if (isa(Function) &&
dyn_cast(Function)->getDescribedFunctionTemplate() &&
StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) {
- std::string ProperArgName =
- getNameForTemplateArgument(dyn_cast(Function)
- ->getDescribedFunctionTemplate()
- ->getTemplateParameters()
- ->asArray(),
- ReturnType.begin()->Spelling);
+ std::string ProperArgName = Function->getReturnType().getAsString();
ReturnType.begin()->Spelling.swap(ProperArgName);
}
ReturnType.append(std::move(After));
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
index ac4f391db5f14a2e0a406008c05d96ab85de0b3b..08210a7ee05954f2efbc308c4899d950855b7614 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
@@ -17,6 +17,8 @@
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -29,8 +31,8 @@ protected:
/// A representation of the APIs this action extracts.
std::unique_ptr API;
- /// A stream to the output file of this action.
- std::unique_ptr OS;
+ /// A stream to the main output file of this action.
+ std::unique_ptr OS;
/// The product this action is extracting API information for.
std::string ProductName;
@@ -46,7 +48,7 @@ protected:
///
/// Use the serializer to generate output symbol graph files from
/// the information gathered during the execution of Action.
- void ImplEndSourceFileAction();
+ void ImplEndSourceFileAction(CompilerInstance &CI);
};
} // namespace clang
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
index e1c3e41c750d40d341c0a024196a4aa3ec20a601..4cb866892b5d00d10c7a3f70c2174b35f103563b 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -14,23 +14,23 @@
#ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
#define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
-#include "clang/AST/Availability.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/OperatorKinds.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/ExtractAPI/DeclarationFragments.h"
-#include "llvm/ADT/FunctionExtras.h"
-
-#include "clang/AST/ASTContext.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/ExtractAPI/API.h"
+#include "clang/ExtractAPI/DeclarationFragments.h"
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include
namespace clang {
@@ -130,12 +130,6 @@ protected:
void recordEnumConstants(EnumRecord *EnumRecord,
const EnumDecl::enumerator_range Constants);
- /// Collect API information for the record fields and associate with the
- /// parent struct.
- void recordRecordFields(RecordRecord *RecordRecord,
- APIRecord::RecordKind FieldKind,
- const RecordDecl::field_range Fields);
-
/// Collect API information for the Objective-C methods and associate with the
/// parent container.
void recordObjCMethods(ObjCContainerRecord *Container,
@@ -172,6 +166,7 @@ private:
return *static_cast(this);
}
+protected:
SmallVector getBases(const CXXRecordDecl *Decl) {
// FIXME: store AccessSpecifier given by inheritance
SmallVector Bases;
@@ -182,49 +177,54 @@ private:
SymbolReference BaseClass;
if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) {
BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString());
- BaseClass.USR = API.recordUSR(
- BaseSpecifier.getType()->getAs()->getDecl());
+ if (auto *TTPTD = BaseSpecifier.getType()
+ ->getAs()
+ ->getDecl()) {
+ SmallString<128> USR;
+ index::generateUSRForDecl(TTPTD, USR);
+ BaseClass.USR = API.copyString(USR);
+ BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD));
+ }
} else {
- CXXRecordDecl *BaseClassDecl =
- BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl();
- BaseClass.Name = BaseClassDecl->getName();
- BaseClass.USR = API.recordUSR(BaseClassDecl);
+ BaseClass = createSymbolReferenceForDecl(
+ *BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl());
}
Bases.emplace_back(BaseClass);
}
return Bases;
}
- APIRecord *determineParentRecord(const DeclContext *Context) {
- SmallString<128> ParentUSR;
- if (Context->getDeclKind() == Decl::TranslationUnit)
- return nullptr;
+ StringRef getOwningModuleName(const Decl &D) {
+ if (auto *OwningModule = D.getImportedOwningModule())
+ return OwningModule->Name;
- index::generateUSRForDecl(dyn_cast(Context), ParentUSR);
+ return {};
+ }
- APIRecord *Parent = API.findRecordForUSR(ParentUSR);
- return Parent;
+ SymbolReference createHierarchyInformationForDecl(const Decl &D) {
+ const auto *Context = cast_if_present(D.getDeclContext());
+
+ if (!Context || isa(Context))
+ return {};
+
+ return createSymbolReferenceForDecl(*Context);
}
-};
-template
-static void modifyRecords(const T &Records, const StringRef &Name) {
- for (const auto &Record : Records) {
- if (Name == Record.second.get()->Name) {
- auto &DeclFragment = Record.second->Declaration;
- DeclFragment.insert(DeclFragment.begin(), " ",
- DeclarationFragments::FragmentKind::Text);
- DeclFragment.insert(DeclFragment.begin(), "typedef",
- DeclarationFragments::FragmentKind::Keyword, "",
- nullptr);
- DeclFragment.insert(--DeclFragment.end(), " { ... } ",
- DeclarationFragments::FragmentKind::Text);
- DeclFragment.insert(--DeclFragment.end(), Name,
- DeclarationFragments::FragmentKind::Identifier);
- break;
- }
+ SymbolReference createSymbolReferenceForDecl(const Decl &D) {
+ SmallString<128> USR;
+ index::generateUSRForDecl(&D, USR);
+
+ APIRecord *Record = API.findRecordForUSR(USR);
+ if (Record)
+ return SymbolReference(Record);
+
+ StringRef Name;
+ if (auto *ND = dyn_cast(&D))
+ Name = ND->getName();
+
+ return API.createSymbolReference(Name, USR, getOwningModuleName(D));
}
-}
+};
template
bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) {
@@ -251,7 +251,8 @@ bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) {
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -267,21 +268,17 @@ bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
if (Decl->isStaticDataMember()) {
- SymbolReference Context;
- // getDeclContext() should return a RecordDecl since we
- // are currently handling a static data member.
- auto *Record = cast(Decl->getDeclContext());
- Context.Name = Record->getName();
- Context.USR = API.recordUSR(Record);
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- API.addStaticField(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Linkage, Comment, Declaration, SubHeading, Context,
- Access, isInSystemHeader(Decl));
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, Access, isInSystemHeader(Decl));
} else
// Add the global variable record to the API set.
- API.addGlobalVar(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Linkage, Comment, Declaration, SubHeading,
- isInSystemHeader(Decl));
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -304,7 +301,7 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl(
return true;
}
- // Skip templated functions.
+ // Skip templated functions that aren't processed here.
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
@@ -321,7 +318,8 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -337,18 +335,19 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
if (Decl->getTemplateSpecializationInfo())
- API.addGlobalFunctionTemplateSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment,
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, isInSystemHeader(Decl));
else
// Add the function record to the API set.
- API.addGlobalFunction(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment, DeclarationFragmentsBuilder::getFragmentsForFunction(Decl),
- SubHeading, Signature, isInSystemHeader(Decl));
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
+ Signature, isInSystemHeader(Decl));
return true;
}
@@ -368,7 +367,8 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) {
Name = QualifiedNameBuffer.str();
}
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -382,13 +382,13 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- EnumRecord *EnumRecord = API.addEnum(
- API.copyString(Name), USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment, Declaration, SubHeading, isInSystemHeader(Decl));
+ auto *ER = API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ isInSystemHeader(Decl));
// Now collect information about the enumerators in this enum.
- getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord,
- Decl->enumerators());
+ getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
return true;
}
@@ -476,13 +476,13 @@ bool ExtractAPIVisitorBase::WalkUpFromNamespaceDecl(
template
bool ExtractAPIVisitorBase::VisitNamespaceDecl(
const NamespaceDecl *Decl) {
-
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
if (Decl->isAnonymousNamespace())
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
@@ -497,10 +497,10 @@ bool ExtractAPIVisitorBase::VisitNamespaceDecl(
DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- API.addNamespace(Parent, Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, isInSystemHeader(Decl));
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -509,14 +509,20 @@ template
bool ExtractAPIVisitorBase::VisitRecordDecl(const RecordDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
+
+ SmallString<128> QualifiedNameBuffer;
// Collect symbol information.
StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);
- if (Name.empty())
- return true;
+ if (Name.empty()) {
+ llvm::raw_svector_ostream OS(QualifiedNameBuffer);
+ Decl->printQualifiedName(OS);
+ Name = QualifiedNameBuffer.str();
+ }
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -531,21 +537,16 @@ bool ExtractAPIVisitorBase::VisitRecordDecl(const RecordDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- auto RecordKind = APIRecord::RK_Struct;
- auto FieldRecordKind = APIRecord::RK_StructField;
-
- if (Decl->isUnion()) {
- RecordKind = APIRecord::RK_Union;
- FieldRecordKind = APIRecord::RK_UnionField;
- }
-
- RecordRecord *RecordRecord = API.addRecord(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, RecordKind, isInSystemHeader(Decl));
-
- // Now collect information about the fields in this struct.
- getDerivedExtractAPIVisitor().recordRecordFields(
- RecordRecord, FieldRecordKind, Decl->fields());
+ if (Decl->isUnion())
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ else
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -558,7 +559,8 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl(
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -580,24 +582,25 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl(
Kind = APIRecord::RecordKind::RK_CXXClass;
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- CXXClassRecord *CXXClassRecord;
+ CXXClassRecord *Record;
if (Decl->getDescribedClassTemplate()) {
// Inject template fragments before class fragments.
Declaration.insert(
Declaration.begin(),
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
- CXXClassRecord = API.addClassTemplate(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()),
- Access, isInSystemHeader(Decl));
+ Record = API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Template(Decl->getDescribedClassTemplate()), Access,
+ isInSystemHeader(Decl));
} else
- CXXClassRecord = API.addCXXClass(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Kind, Access, isInSystemHeader(Decl));
+ Record = API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Kind, Access, isInSystemHeader(Decl));
- CXXClassRecord->Bases = getBases(Decl);
+ Record->Bases = getBases(Decl);
return true;
}
@@ -614,7 +617,8 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl(
if (isa(Decl) || isa(Decl))
return true;
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -627,14 +631,10 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl(
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()),
- ParentUSR);
- auto *Parent = API.findRecordForUSR(ParentUSR);
- if (Decl->isTemplated()) {
- FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
- API.addCXXMethodTemplate(
- API.findRecordForUSR(ParentUSR), Decl->getName(), USR, Loc,
+ if (FunctionTemplateDecl *TemplateDecl =
+ Decl->getDescribedFunctionTemplate()) {
+ API.createRecord(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
TemplateDecl),
@@ -642,27 +642,27 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl(
DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
Template(TemplateDecl), isInSystemHeader(Decl));
} else if (Decl->getTemplateSpecializationInfo())
- API.addCXXMethodTemplateSpec(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isOverloadedOperator())
- API.addCXXInstanceMethod(
- Parent, API.copyString(Decl->getNameAsString()), USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
+ API.createRecord(
+ USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
+ Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isStatic())
- API.addCXXStaticMethod(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
else
- API.addCXXInstanceMethod(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
@@ -673,9 +673,13 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl(
template
bool ExtractAPIVisitorBase::VisitCXXConstructorDecl(
const CXXConstructorDecl *Decl) {
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
+ Decl->isImplicit())
+ return true;
- StringRef Name = API.copyString(Decl->getNameAsString());
- StringRef USR = API.recordUSR(Decl);
+ auto Name = Decl->getNameAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -692,22 +696,24 @@ bool ExtractAPIVisitorBase::VisitCXXConstructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
return true;
}
template
bool ExtractAPIVisitorBase::VisitCXXDestructorDecl(
const CXXDestructorDecl *Decl) {
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
+ Decl->isImplicit())
+ return true;
- StringRef Name = API.copyString(Decl->getNameAsString());
- StringRef USR = API.recordUSR(Decl);
+ auto Name = Decl->getNameAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -724,13 +730,10 @@ bool ExtractAPIVisitorBase::VisitCXXDestructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
return true;
}
@@ -740,7 +743,8 @@ bool ExtractAPIVisitorBase::VisitConceptDecl(const ConceptDecl *Decl) {
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -752,9 +756,10 @@ bool ExtractAPIVisitorBase::VisitConceptDecl(const ConceptDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForConcept(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.addConcept(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment, Declaration, SubHeading, Template(Decl),
- isInSystemHeader(Decl));
+ API.createRecord