aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/cmake/caches/Fuchsia.cmake2
-rw-r--r--clang/docs/ReleaseNotes.rst10
-rw-r--r--clang/include/clang/AST/Decl.h12
-rw-r--r--clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h50
-rw-r--r--clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h8
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td6
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td4
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticIDs.h2
-rw-r--r--clang/include/clang/Basic/TokenKinds.def46
-rw-r--r--clang/include/clang/Basic/arm_neon.td31
-rw-r--r--clang/include/clang/Driver/Options.td23
-rw-r--r--clang/include/clang/ExtractAPI/API.h1547
-rw-r--r--clang/include/clang/ExtractAPI/APIRecords.inc103
-rw-r--r--clang/include/clang/ExtractAPI/DeclarationFragments.h14
-rw-r--r--clang/include/clang/ExtractAPI/ExtractAPIActionBase.h8
-rw-r--r--clang/include/clang/ExtractAPI/ExtractAPIVisitor.h674
-rw-r--r--clang/include/clang/ExtractAPI/FrontendActions.h6
-rw-r--r--clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h172
-rw-r--r--clang/include/clang/ExtractAPI/Serialization/SerializerBase.h314
-rw-r--r--clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h254
-rw-r--r--clang/include/clang/Frontend/FrontendOptions.h25
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h2
-rw-r--r--clang/include/clang/Serialization/ASTWriter.h8
-rw-r--r--clang/lib/AST/ASTImporter.cpp4
-rw-r--r--clang/lib/AST/DeclBase.cpp6
-rw-r--r--clang/lib/AST/TypePrinter.cpp13
-rw-r--r--clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp49
-rw-r--r--clang/lib/Basic/Targets/Mips.h8
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp5
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp10
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp15
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp6
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp6
-rw-r--r--clang/lib/CodeGen/Targets/X86.cpp6
-rw-r--r--clang/lib/Driver/Driver.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp33
-rw-r--r--clang/lib/ExtractAPI/API.cpp544
-rw-r--r--clang/lib/ExtractAPI/DeclarationFragments.cpp71
-rw-r--r--clang/lib/ExtractAPI/ExtractAPIConsumer.cpp112
-rw-r--r--clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp943
-rw-r--r--clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp6
-rw-r--r--clang/lib/Format/Format.cpp2
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp2
-rw-r--r--clang/lib/Frontend/PrecompiledPreamble.cpp3
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp10
-rw-r--r--clang/lib/Headers/__stddef_unreachable.h4
-rw-r--r--clang/lib/Sema/SemaDecl.cpp17
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaExpr.cpp2
-rw-r--r--clang/lib/Sema/SemaStmtAttr.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp1
-rw-r--r--clang/lib/Serialization/ASTReader.cpp10
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp138
-rw-r--r--clang/lib/Serialization/GeneratePCH.cpp21
-rw-r--r--clang/lib/Tooling/CMakeLists.txt6
-rw-r--r--clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c485
-rw-r--r--clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c472
-rw-r--r--clang/test/CodeGen/allow-ubsan-check.c207
-rw-r--r--clang/test/CodeGen/arm-v8.2a-neon-intrinsics-generic.c600
-rw-r--r--clang/test/CodeGen/arm-v8.2a-neon-intrinsics.c178
-rw-r--r--clang/test/CodeGen/cx-complex-range.c656
-rw-r--r--clang/test/CodeGen/pseudo-probe-emit.c8
-rw-r--r--clang/test/CodeGen/remote-traps.c32
-rw-r--r--clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp39
-rw-r--r--clang/test/CodeGenCXX/x86_32-vaarg.cpp21
-rw-r--r--clang/test/Driver/mcmodel.c1
-rw-r--r--clang/test/Driver/module-output.cppm8
-rw-r--r--clang/test/ExtractAPI/anonymous_record_no_typedef.c3
-rw-r--r--clang/test/ExtractAPI/availability.c2
-rw-r--r--clang/test/ExtractAPI/bool.c2
-rw-r--r--clang/test/ExtractAPI/bool.cpp2
-rw-r--r--clang/test/ExtractAPI/class.cpp2
-rw-r--r--clang/test/ExtractAPI/class_template.cpp2
-rw-r--r--clang/test/ExtractAPI/class_template_param_inheritance.cpp2
-rw-r--r--clang/test/ExtractAPI/class_template_partial_spec.cpp4
-rw-r--r--clang/test/ExtractAPI/class_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/concept.cpp2
-rw-r--r--clang/test/ExtractAPI/constructor_destructor.cpp6
-rw-r--r--clang/test/ExtractAPI/conversions.cpp2
-rw-r--r--clang/test/ExtractAPI/emit-symbol-graph/multi_file.c7
-rw-r--r--clang/test/ExtractAPI/emit-symbol-graph/single_file.c5
-rw-r--r--clang/test/ExtractAPI/enum.c2
-rw-r--r--clang/test/ExtractAPI/field_template.cpp2
-rw-r--r--clang/test/ExtractAPI/function_noexcepts.cpp2
-rw-r--r--clang/test/ExtractAPI/global_func_template.cpp2
-rw-r--r--clang/test/ExtractAPI/global_func_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/global_record.c2
-rw-r--r--clang/test/ExtractAPI/global_record_multifile.c2
-rw-r--r--clang/test/ExtractAPI/global_var_template.cpp2
-rw-r--r--clang/test/ExtractAPI/global_var_template_partial_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/global_var_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/known_files_only.c101
-rw-r--r--clang/test/ExtractAPI/language.c6
-rw-r--r--clang/test/ExtractAPI/macro_undefined.c2
-rw-r--r--clang/test/ExtractAPI/macros.c2
-rw-r--r--clang/test/ExtractAPI/metadata_and_module.c32
-rw-r--r--clang/test/ExtractAPI/method_template.cpp2
-rw-r--r--clang/test/ExtractAPI/method_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/methods.cpp660
-rw-r--r--clang/test/ExtractAPI/multiple_inheritance.cpp2
-rw-r--r--clang/test/ExtractAPI/namespace.cpp2
-rw-r--r--clang/test/ExtractAPI/nested_namespaces.cpp2
-rw-r--r--clang/test/ExtractAPI/objc_block.m1567
-rw-r--r--clang/test/ExtractAPI/objc_category.m338
-rw-r--r--clang/test/ExtractAPI/objc_external_category.m49
-rw-r--r--clang/test/ExtractAPI/objc_id_protocol.m357
-rw-r--r--clang/test/ExtractAPI/objc_instancetype.m4
-rw-r--r--clang/test/ExtractAPI/objc_interface.m1033
-rw-r--r--clang/test/ExtractAPI/objc_module_category.m404
-rw-r--r--clang/test/ExtractAPI/objc_property.m600
-rw-r--r--clang/test/ExtractAPI/objc_protocol.m2
-rw-r--r--clang/test/ExtractAPI/objc_various_categories.m507
-rw-r--r--clang/test/ExtractAPI/operator_overload.cpp2
-rw-r--r--clang/test/ExtractAPI/relative_include.m2
-rw-r--r--clang/test/ExtractAPI/simple_inheritance.cpp2
-rw-r--r--clang/test/ExtractAPI/struct.c2
-rw-r--r--clang/test/ExtractAPI/typedef.c464
-rw-r--r--clang/test/ExtractAPI/typedef_anonymous_record.c612
-rw-r--r--clang/test/ExtractAPI/typedef_chain.c2
-rw-r--r--clang/test/ExtractAPI/typedef_struct_enum.c561
-rw-r--r--clang/test/ExtractAPI/underscored.c411
-rw-r--r--clang/test/ExtractAPI/union.c4
-rw-r--r--clang/test/ExtractAPI/vfs_redirected_include.m2
-rw-r--r--clang/test/Index/extract-api-cursor.m9
-rw-r--r--clang/test/InstallAPI/driver-invalid-options.test6
-rw-r--r--clang/test/Interpreter/inline-asm.cpp17
-rw-r--r--clang/test/Modules/reduced-bmi-size.cppm16
-rw-r--r--clang/test/Parser/c2x-typeof-ext-warns.c7
-rw-r--r--clang/test/Sema/code_align.c22
-rw-r--r--clang/test/SemaCXX/typeof_unqual.cpp5
-rw-r--r--clang/test/SemaCXX/warn-unused-but-set-variables-cpp.cpp8
-rw-r--r--clang/test/SemaHLSL/ArrayTemporary.ll76
-rw-r--r--clang/tools/clang-repl/ClangRepl.cpp1
-rw-r--r--clang/tools/libclang/CXExtractAPI.cpp73
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp28
-rw-r--r--clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp72
-rw-r--r--clang/unittests/Format/TokenAnnotatorTest.cpp4
-rw-r--r--clang/www/c_status.html5
140 files changed, 6384 insertions, 9863 deletions
diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake
index df69d7d..393d97a 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/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d5ce54e..92032c0 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
------------------
@@ -328,6 +331,13 @@ 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.
+
+- Clang emits a ``-Wunused-but-set-variable`` warning on C++ variables whose declaration
+ (with initializer) entirely consist the condition expression of a if/while/for construct
+ but are not actually used in the body of the if/while/for construct. Fixes #GH41447
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index a5879591f..5f1f83b 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -1100,6 +1100,9 @@ protected:
LLVM_PREFERRED_TYPE(bool)
unsigned EscapingByref : 1;
+
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned IsCXXCondDecl : 1;
};
union {
@@ -1589,6 +1592,15 @@ public:
NonParmVarDeclBits.EscapingByref = true;
}
+ bool isCXXCondDecl() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsCXXCondDecl;
+ }
+
+ void setCXXCondDecl() {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsCXXCondDecl = true;
+ }
+
/// Determines if this variable's alignment is dependent.
bool hasDependentAlignment() const;
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index c30bccd..9a65f76 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<WidenResult> 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 0c81e2f..b262732 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/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 592ed3b..3d86f75 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=<directory>">;
+
+def err_drv_unexpected_symbol_graph_output : Error<
+ "Unexpected output symbol graph '%1'; please provide --symbol-graph-dir=<directory> instead">;
+
def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
InGroup<DiagGroup<"slash-u-filename">>;
def note_use_dashdash : Note<
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index ba23cf8..14b08d4 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<ExtractAPIMisuse>;
+
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 520168f..5251774 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 5ff782c..bce7605 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/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 3a96f8a..800af0e 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 f16de97..7edac5a 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 f5289fb..12e8dc7 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -802,9 +802,11 @@ def B : JoinedOrSeparate<["-"], "B">, MetaVarName<"<prefix>">,
HelpText<"Search $prefix$file for executables, libraries, and data files. "
"If $prefix is a directory, search $prefix/$file">;
def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
+ Visibility<[ClangOption, FlangOption]>,
HelpText<"Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">;
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
+ Visibility<[ClangOption, FlangOption]>,
HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">;
def gcc_triple_EQ : Joined<["--"], "gcc-triple=">,
@@ -1507,14 +1509,29 @@ def extract_api : Flag<["-"], "extract-api">,
def product_name_EQ: Joined<["--"], "product-name=">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<FrontendOpts<"ProductName">>;
-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<FrontendOpts<"SymbolGraphOutputDir">>;
+ HelpText<"Generate Extract API information as a side effect of compilation.">,
+ MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraph">>;
+def emit_extension_symbol_graphs: Flag<["--"], "emit-extension-symbol-graphs">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Generate additional symbol graphs for extended modules.">,
+ MarshallingInfoFlag<FrontendOpts<"EmitExtensionSymbolGraphs">>;
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<FrontendOpts<"ExtractAPIIgnoresFileList">>;
+def symbol_graph_dir_EQ: Joined<["--"], "symbol-graph-dir=">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Directory in which to emit symbol graphs.">,
+ MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
+def emit_pretty_sgf: Flag<["--"], "pretty-sgf">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Emit pretty printed symbol graphs">,
+ MarshallingInfoFlag<FrontendOpts<"EmitPrettySymbolGraphs">>;
+def emit_sgf_symbol_labels_for_testing: Flag<["--"], "emit-sgf-symbol-labels-for-testing">,
+ Visibility<[CC1Option]>,
+ MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraphSymbolLabelsForTesting">>;
def e : Separate<["-"], "e">, Flags<[LinkerInput]>, Group<Link_Group>;
def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index b220db2..92cacf6 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 <cstddef>
+#include <iterator>
#include <memory>
+#include <optional>
#include <type_traits>
namespace clang {
@@ -149,15 +157,58 @@ public:
/// \endcode
using DocComment = std::vector<RawComment::CommentLine>;
-// 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_iterator>;
+ 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<std::unique_ptr<EnumConstantRecord>> 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<std::unique_ptr<RecordFieldRecord>> 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<std::unique_ptr<ObjCMethodRecord>> Methods;
- SmallVector<std::unique_ptr<ObjCPropertyRecord>> Properties;
- SmallVector<std::unique_ptr<ObjCInstanceVariableRecord>> Ivars;
+struct ObjCContainerRecord : APIRecord, RecordContext {
SmallVector<SymbolReference> 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<std::unique_ptr<CXXFieldRecord>> Fields;
- SmallVector<std::unique_ptr<CXXMethodRecord>> Methods;
+struct CXXClassRecord : APIRecord, RecordContext {
SmallVector<SymbolReference> 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<StringRef> 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<ObjCCategoryRecord *> 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 <typename RecordTy>
-struct has_function_signature : public std::false_type {};
-template <>
-struct has_function_signature<GlobalFunctionRecord> : public std::true_type {};
-template <>
-struct has_function_signature<ObjCMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<ObjCInstanceMethodRecord>
- : public std::true_type {};
-template <>
-struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<CXXInstanceMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<CXXStaticMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
-};
-template <>
-struct has_function_signature<CXXMethodTemplateSpecializationRecord>
- : public std::true_type {};
-
-template <typename RecordTy> struct has_access : public std::false_type {};
-template <> struct has_access<CXXInstanceMethodRecord> : public std::true_type {};
-template <> struct has_access<CXXStaticMethodRecord> : public std::true_type {};
-template <> struct has_access<CXXFieldRecord> : public std::true_type {};
-template <>
-struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
-template <>
-struct has_access<CXXMethodTemplateSpecializationRecord>
- : public std::true_type {};
-template <>
-struct has_access<CXXFieldTemplateRecord> : public std::true_type {};
-template <> struct has_access<CXXClassRecord> : public std::true_type {};
-template <> struct has_access<ClassTemplateRecord> : public std::true_type {};
-template <>
-struct has_access<ClassTemplateSpecializationRecord> : public std::true_type {};
-template <>
-struct has_access<ClassTemplatePartialSpecializationRecord>
- : public std::true_type {};
-
-template <typename RecordTy> struct has_template : public std::false_type {};
-template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
-template <>
-struct has_template<ClassTemplatePartialSpecializationRecord>
- : public std::true_type {};
-template <> struct has_template<ConceptRecord> : public std::true_type {};
-template <>
-struct has_template<GlobalVariableTemplateRecord> : public std::true_type {};
-template <>
-struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
- : public std::true_type {};
-template <>
-struct has_template<CXXMethodTemplateRecord> : public std::true_type {};
-template <>
-struct has_template<CXXFieldTemplateRecord> : public std::true_type {};
-
-template <>
-struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
-template <>
-struct has_function_signature<GlobalFunctionTemplateRecord>
- : public std::true_type {};
-template <>
-struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
- : 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 RecordTy, typename... CtorArgsContTy>
+ typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
+ createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
+
+ ArrayRef<const APIRecord *> 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<APIRecord, APIRecordDeleter>;
+ llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable;
+ std::vector<const APIRecord *> 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 RecordTy, typename... CtorArgsContTy>
+typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, 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<CtorArgsContTy>(CtorArgs)...);
+ // Store the record in the record lookup map
+ Result.first->second = APIRecordStoredPtr(Record);
+
+ if (auto *ParentContext =
+ dyn_cast_if_present<RecordContext>(Record->Parent.Record))
+ ParentContext->addToRecordChain(Record);
+ else
+ TopLevelRecords.push_back(Record);
+ } else {
+ Record = dyn_cast<RecordTy>(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 <typename RecordTy,
- typename =
- std::enable_if_t<std::is_base_of<APIRecord, RecordTy>::value>>
- using RecordMap = llvm::MapVector<StringRef, std::unique_ptr<RecordTy>>;
+ 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 <typename FromTy,
+ bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>>
+struct ToRecordContextCastInfoWrapper {
+ static_assert(std::is_base_of_v<APIRecord, FromTy>,
+ "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<NamespaceRecord> &getNamespaces() const { return Namespaces; }
- const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
- return GlobalFunctions;
- }
- const RecordMap<GlobalFunctionTemplateRecord> &
- getGlobalFunctionTemplates() const {
- return GlobalFunctionTemplates;
- }
- const RecordMap<GlobalFunctionTemplateSpecializationRecord> &
- getGlobalFunctionTemplateSpecializations() const {
- return GlobalFunctionTemplateSpecializations;
- }
- const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
- return GlobalVariables;
- }
- const RecordMap<GlobalVariableTemplateRecord> &
- getGlobalVariableTemplates() const {
- return GlobalVariableTemplates;
+ static RecordContext *doCast(FromTy *From) {
+ return APIRecord::castToRecordContext(From);
}
- const RecordMap<StaticFieldRecord> &getStaticFields() const {
- return StaticFields;
- }
- const RecordMap<GlobalVariableTemplateSpecializationRecord> &
- getGlobalVariableTemplateSpecializations() const {
- return GlobalVariableTemplateSpecializations;
- }
- const RecordMap<GlobalVariableTemplatePartialSpecializationRecord> &
- getGlobalVariableTemplatePartialSpecializations() const {
- return GlobalVariableTemplatePartialSpecializations;
- }
- const RecordMap<EnumRecord> &getEnums() const { return Enums; }
- const RecordMap<RecordRecord> &getRecords() const { return Records; }
- const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
- const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
- return CXXMethodTemplates;
- }
- const RecordMap<CXXInstanceMethodRecord> &getCXXInstanceMethods() const {
- return CXXInstanceMethods;
- }
- const RecordMap<CXXStaticMethodRecord> &getCXXStaticMethods() const {
- return CXXStaticMethods;
- }
- const RecordMap<CXXFieldRecord> &getCXXFields() const { return CXXFields; }
- const RecordMap<CXXMethodTemplateSpecializationRecord> &
- getCXXMethodTemplateSpecializations() const {
- return CXXMethodTemplateSpecializations;
- }
- const RecordMap<CXXFieldTemplateRecord> &getCXXFieldTemplates() const {
- return CXXFieldTemplates;
- }
- const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
- return ClassTemplates;
- }
- const RecordMap<ClassTemplateSpecializationRecord> &
- getClassTemplateSpecializations() const {
- return ClassTemplateSpecializations;
+};
+
+// Selected when FromTy is a known subclass of RecordContext.
+template <typename FromTy> struct ToRecordContextCastInfoWrapper<FromTy, true> {
+ static_assert(std::is_base_of_v<APIRecord, FromTy>,
+ "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<RecordContext *>(From);
}
- const RecordMap<ClassTemplatePartialSpecializationRecord> &
- getClassTemplatePartialSpecializations() const {
- return ClassTemplatePartialSpecializations;
+};
+
+// Helper type for implementing casting to RecordContext pointers.
+// Selected when ToTy isn't a known subclass of RecordContext
+template <typename ToTy,
+ bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>>
+struct FromRecordContextCastInfoWrapper {
+ static_assert(
+ std::is_base_of_v<APIRecord, ToTy>,
+ "Can only class RecordContext to APIRecord and derived classes");
+
+ static bool isPossible(RecordContext *Ctx) {
+ return ToTy::classofKind(Ctx->getKind());
}
- const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
- const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
- return ObjCCategories;
+
+ static ToTy *doCast(RecordContext *Ctx) {
+ return APIRecord::castFromRecordContext(Ctx);
}
- const RecordMap<ObjCInterfaceRecord> &getObjCInterfaces() const {
- return ObjCInterfaces;
+};
+
+// Selected when ToTy is a known subclass of RecordContext.
+template <typename ToTy> struct FromRecordContextCastInfoWrapper<ToTy, true> {
+ static_assert(
+ std::is_base_of_v<APIRecord, ToTy>,
+ "Can only class RecordContext to APIRecord and derived classes");
+ static bool isPossible(RecordContext *Ctx) {
+ return ToTy::classof(Ctx->getKind());
}
- const RecordMap<ObjCProtocolRecord> &getObjCProtocols() const {
- return ObjCProtocols;
+ static RecordContext *doCast(RecordContext *Ctx) {
+ return static_cast<ToTy *>(Ctx);
}
- const RecordMap<MacroDefinitionRecord> &getMacros() const { return Macros; }
- const RecordMap<TypedefRecord> &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 <typename FromTy>
+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<FromTy>::doCast(
+ From);
+ }
+};
- llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
- RecordMap<NamespaceRecord> Namespaces;
- RecordMap<GlobalFunctionRecord> GlobalFunctions;
- RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
- RecordMap<GlobalFunctionTemplateSpecializationRecord>
- GlobalFunctionTemplateSpecializations;
- RecordMap<GlobalVariableRecord> GlobalVariables;
- RecordMap<GlobalVariableTemplateRecord> GlobalVariableTemplates;
- RecordMap<GlobalVariableTemplateSpecializationRecord>
- GlobalVariableTemplateSpecializations;
- RecordMap<GlobalVariableTemplatePartialSpecializationRecord>
- GlobalVariableTemplatePartialSpecializations;
- RecordMap<ConceptRecord> Concepts;
- RecordMap<StaticFieldRecord> StaticFields;
- RecordMap<EnumRecord> Enums;
- RecordMap<RecordRecord> Records;
- RecordMap<CXXClassRecord> CXXClasses;
- RecordMap<CXXFieldRecord> CXXFields;
- RecordMap<CXXMethodRecord> CXXMethods;
- RecordMap<CXXInstanceMethodRecord> CXXInstanceMethods;
- RecordMap<CXXStaticMethodRecord> CXXStaticMethods;
- RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
- RecordMap<CXXMethodTemplateSpecializationRecord>
- CXXMethodTemplateSpecializations;
- RecordMap<CXXFieldTemplateRecord> CXXFieldTemplates;
- RecordMap<ClassTemplateRecord> ClassTemplates;
- RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
- RecordMap<ClassTemplatePartialSpecializationRecord>
- ClassTemplatePartialSpecializations;
- RecordMap<ObjCCategoryRecord> ObjCCategories;
- RecordMap<ObjCInterfaceRecord> ObjCInterfaces;
- RecordMap<ObjCProtocolRecord> ObjCProtocols;
- RecordMap<MacroDefinitionRecord> Macros;
- RecordMap<TypedefRecord> Typedefs;
+template <typename FromTy>
+struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
+ : public ConstStrippingForwardingCast<
+ ::clang::extractapi::RecordContext, const FromTy *,
+ CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
+
+template <typename ToTy>
+struct CastInfo<ToTy, ::clang::extractapi::RecordContext *>
+ : public NullableValueCastFailed<ToTy *>,
+ public DefaultDoCastIfPossible<
+ ToTy *, ::clang::extractapi::RecordContext *,
+ CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {
+ 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<ToTy>::doCast(
+ Ctx);
+ }
};
-} // namespace extractapi
-} // namespace clang
+template <typename ToTy>
+struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *>
+ : public ConstStrippingForwardingCast<
+ ToTy, const ::clang::extractapi::RecordContext *,
+ CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {};
+
+} // 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 0000000..15fee80
--- /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 8a3a22d..94392c1 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -180,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);
@@ -192,12 +204,14 @@ public:
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
private:
+ DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
std::vector<Fragment> Fragments;
};
class AccessControl {
public:
AccessControl(std::string Access) : Access(Access) {}
+ AccessControl() : Access("public") {}
const std::string &getAccess() const { return Access; }
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
index ac4f391..08210a7 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<extractapi::APISet> API;
- /// A stream to the output file of this action.
- std::unique_ptr<raw_pwrite_stream> OS;
+ /// A stream to the main output file of this action.
+ std::unique_ptr<llvm::raw_pwrite_stream> 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 e1c3e41..4cb8668 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 <type_traits>
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<Derived *>(this);
}
+protected:
SmallVector<SymbolReference> getBases(const CXXRecordDecl *Decl) {
// FIXME: store AccessSpecifier given by inheritance
SmallVector<SymbolReference> 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<TemplateTypeParmType>()->getDecl());
+ if (auto *TTPTD = BaseSpecifier.getType()
+ ->getAs<TemplateTypeParmType>()
+ ->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<Decl>(Context), ParentUSR);
+ return {};
+ }
- APIRecord *Parent = API.findRecordForUSR(ParentUSR);
- return Parent;
+ SymbolReference createHierarchyInformationForDecl(const Decl &D) {
+ const auto *Context = cast_if_present<Decl>(D.getDeclContext());
+
+ if (!Context || isa<TranslationUnitDecl>(Context))
+ return {};
+
+ return createSymbolReferenceForDecl(*Context);
}
-};
-template <typename T>
-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<NamedDecl>(&D))
+ Name = ND->getName();
+
+ return API.createSymbolReference(Name, USR, getOwningModuleName(D));
}
-}
+};
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
@@ -251,7 +251,8 @@ bool ExtractAPIVisitorBase<Derived>::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<Derived>::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<RecordDecl>(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<StaticFieldRecord>(
+ 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<GlobalVariableRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -304,7 +301,7 @@ bool ExtractAPIVisitorBase<Derived>::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<Derived>::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<Derived>::VisitFunctionDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
if (Decl->getTemplateSpecializationInfo())
- API.addGlobalFunctionTemplateSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment,
+ API.createRecord<GlobalFunctionTemplateSpecializationRecord>(
+ 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<GlobalFunctionRecord>(
+ 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<Derived>::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<Derived>::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<EnumRecord>(
+ 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<Derived>::WalkUpFromNamespaceDecl(
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::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<Derived>::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<NamespaceRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -509,14 +509,20 @@ template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::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<Derived>::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<UnionRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ else
+ API.createRecord<StructRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -558,7 +559,8 @@ bool ExtractAPIVisitorBase<Derived>::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<Derived>::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<ClassTemplateRecord>(
+ 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<CXXClassRecord>(
+ 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<Derived>::VisitCXXMethodDecl(
if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(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<Derived>::VisitCXXMethodDecl(
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(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<CXXMethodTemplateRecord>(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
TemplateDecl),
@@ -642,27 +642,27 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
Template(TemplateDecl), isInSystemHeader(Decl));
} else if (Decl->getTemplateSpecializationInfo())
- API.addCXXMethodTemplateSpec(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord<CXXMethodTemplateSpecializationRecord>(
+ 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<CXXInstanceMethodRecord>(
+ 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<CXXStaticMethodRecord>(
+ 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<CXXInstanceMethodRecord>(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
@@ -673,9 +673,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::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<Derived>::VisitCXXConstructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+
+ API.createRecord<CXXConstructorRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
return true;
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::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<Derived>::VisitCXXDestructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord<CXXDestructorRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
return true;
}
@@ -740,7 +743,8 @@ bool ExtractAPIVisitorBase<Derived>::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<Derived>::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<ConceptRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -765,7 +770,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
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;
@@ -779,14 +785,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading,
+ auto *CTSR = API.createRecord<ClassTemplateSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
DeclarationFragmentsBuilder::getAccessControl(Decl),
isInSystemHeader(Decl));
- ClassTemplateSpecializationRecord->Bases = getBases(Decl);
+ CTSR->Bases = getBases(Decl);
return true;
}
@@ -799,7 +804,8 @@ bool ExtractAPIVisitorBase<Derived>::
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;
@@ -811,15 +817,13 @@ bool ExtractAPIVisitorBase<Derived>::
getFragmentsForClassTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- auto *ClassTemplatePartialSpecRecord =
- API.addClassTemplatePartialSpecialization(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment, Declaration, SubHeading, Template(Decl),
- DeclarationFragmentsBuilder::getAccessControl(Decl),
- isInSystemHeader(Decl));
+ auto *CTPSR = API.createRecord<ClassTemplatePartialSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl),
+ isInSystemHeader(Decl));
- ClassTemplatePartialSpecRecord->Bases = getBases(Decl);
+ CTPSR->Bases = getBases(Decl);
return true;
}
@@ -832,7 +836,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
// 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();
@@ -853,20 +858,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord)
- API.addCXXFieldTemplate(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading,
- DeclarationFragmentsBuilder::getAccessControl(Decl),
- Template(Decl), isInSystemHeader(Decl));
+ API.createRecord<CXXFieldTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl),
+ Template(Decl), isInSystemHeader(Decl));
else
- API.addGlobalVariableTemplate(Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl),
- Linkage, Comment, Declaration, SubHeading,
- Template(Decl), isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -878,7 +880,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
// 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();
@@ -894,9 +897,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.addGlobalVariableTemplateSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableTemplateSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -908,7 +912,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
// 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();
@@ -923,9 +928,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
getFragmentsForVarTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.addGlobalVariableTemplatePartialSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, Template(Decl), isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableTemplatePartialSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -939,7 +945,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
// 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();
@@ -954,8 +961,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(
Decl->getTemplatedDecl());
- API.addGlobalFunctionTemplate(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ API.createRecord<GlobalFunctionTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
@@ -970,7 +978,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
// 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();
@@ -988,24 +997,23 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
// Collect super class information.
SymbolReference SuperClass;
- if (const auto *SuperClassDecl = Decl->getSuperClass()) {
- SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
- SuperClass.USR = API.recordUSR(SuperClassDecl);
- }
+ if (const auto *SuperClassDecl = Decl->getSuperClass())
+ SuperClass = createSymbolReferenceForDecl(*SuperClassDecl);
- ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
+ auto *InterfaceRecord = API.createRecord<ObjCInterfaceRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, SuperClass, isInSystemHeader(Decl));
// Record all methods (selectors). This doesn't include automatically
// synthesized property methods.
- getDerivedExtractAPIVisitor().recordObjCMethods(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(InterfaceRecord,
Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCProperties(InterfaceRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCInstanceVariables(InterfaceRecord,
Decl->ivars());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(InterfaceRecord,
Decl->protocols());
return true;
@@ -1019,7 +1027,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
// 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());
DocComment Comment;
@@ -1034,15 +1043,15 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, isInSystemHeader(Decl));
+ auto *ProtoRecord = API.createRecord<ObjCProtocolRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ isInSystemHeader(Decl));
- getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord,
- Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ObjCProtocolRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(ProtoRecord, Decl->methods());
+ getDerivedExtractAPIVisitor().recordObjCProperties(ProtoRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCProtocolRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(ProtoRecord,
Decl->protocols());
return true;
@@ -1061,25 +1070,36 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
- // Add the notion of typedef for tag type (struct or enum) of the same name.
- if (const ElaboratedType *ET =
- dyn_cast<ElaboratedType>(Decl->getUnderlyingType())) {
- if (const TagType *TagTy = dyn_cast<TagType>(ET->desugar())) {
- if (Decl->getName() == TagTy->getDecl()->getName()) {
- if (isa<RecordDecl>(TagTy->getDecl())) {
- modifyRecords(API.getRecords(), Decl->getName());
- }
- if (TagTy->getDecl()->isEnum()) {
- modifyRecords(API.getEnums(), Decl->getName());
- }
+ StringRef Name = Decl->getName();
+
+ // If the underlying type was defined as part of the typedef modify it's
+ // fragments directly and pretend the typedef doesn't exist.
+ if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
+ if (TagDecl->getName() == Decl->getName() &&
+ TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition()) {
+ SmallString<128> TagUSR;
+ index::generateUSRForDecl(TagDecl, TagUSR);
+ if (auto *Record = API.findRecordForUSR(TagUSR)) {
+ DeclarationFragments LeadingFragments;
+ LeadingFragments.append("typedef",
+ DeclarationFragments::FragmentKind::Keyword, "",
+ nullptr);
+ LeadingFragments.appendSpace();
+ Record->Declaration.removeTrailingSemicolon()
+ .insert(Record->Declaration.begin(), std::move(LeadingFragments))
+ .append(" { ... } ", DeclarationFragments::FragmentKind::Text)
+ .append(Name, DeclarationFragments::FragmentKind::Identifier)
+ .appendSemicolon();
+
+ return true;
}
}
}
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
- StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
DocComment Comment;
if (auto *RawComment =
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
@@ -1091,11 +1111,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
API);
- API.addTypedef(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment,
- DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
- DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
- isInSystemHeader(Decl));
+ API.createRecord<TypedefRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment,
+ DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
+ DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
+ isInSystemHeader(Decl));
return true;
}
@@ -1107,7 +1128,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
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;
@@ -1122,29 +1144,20 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
DeclarationFragmentsBuilder::getSubHeading(Decl);
const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface();
- SymbolReference Interface(InterfaceDecl->getName(),
- API.recordUSR(InterfaceDecl));
-
- bool IsFromExternalModule = true;
- for (const auto &Interface : API.getObjCInterfaces()) {
- if (InterfaceDecl->getName() == Interface.second.get()->Name) {
- IsFromExternalModule = false;
- break;
- }
- }
+ SymbolReference Interface = createSymbolReferenceForDecl(*InterfaceDecl);
- ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Interface, isInSystemHeader(Decl),
- IsFromExternalModule);
+ auto *CategoryRecord = API.createRecord<ObjCCategoryRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Interface, isInSystemHeader(Decl));
- getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(CategoryRecord,
Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCProperties(CategoryRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCInstanceVariables(CategoryRecord,
Decl->ivars());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(CategoryRecord,
Decl->protocols());
return true;
@@ -1158,7 +1171,8 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
for (const auto *Constant : Constants) {
// Collect symbol information.
StringRef Name = Constant->getName();
- StringRef USR = API.recordUSR(Constant);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Constant, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Constant->getLocation());
DocComment Comment;
@@ -1173,51 +1187,26 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Constant);
- API.addEnumConstant(EnumRecord, Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Constant), Comment,
- Declaration, SubHeading, isInSystemHeader(Constant));
- }
-}
-
-/// Collect API information for the struct fields and associate with the
-/// parent struct.
-template <typename Derived>
-void ExtractAPIVisitorBase<Derived>::recordRecordFields(
- RecordRecord *RecordRecord, APIRecord::RecordKind FieldKind,
- const RecordDecl::field_range Fields) {
- for (const auto *Field : Fields) {
- // Collect symbol information.
- StringRef Name = Field->getName();
- StringRef USR = API.recordUSR(Field);
- PresumedLoc Loc =
- Context.getSourceManager().getPresumedLoc(Field->getLocation());
- DocComment Comment;
- if (auto *RawComment =
- getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Field))
- Comment = RawComment->getFormattedLines(Context.getSourceManager(),
- Context.getDiagnostics());
-
- // Build declaration fragments and sub-heading for the struct field.
- DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForField(Field);
- DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(Field);
-
- API.addRecordField(
- RecordRecord, Name, USR, Loc, AvailabilityInfo::createFromDecl(Field),
- Comment, Declaration, SubHeading, FieldKind, isInSystemHeader(Field));
+ API.createRecord<EnumConstantRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Constant), Loc,
+ AvailabilityInfo::createFromDecl(Constant), Comment, Declaration,
+ SubHeading, isInSystemHeader(Constant));
}
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
- if (Decl->getDeclContext()->getDeclKind() == Decl::Record)
+ // ObjCIvars are handled separately
+ if (isa<ObjCIvarDecl>(Decl) || isa<ObjCAtDefsFieldDecl>(Decl))
return true;
- if (isa<ObjCIvarDecl>(Decl))
+
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
+
// 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());
DocComment Comment;
@@ -1231,22 +1220,40 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForField(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXField(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, Access, isInSystemHeader(Decl));
+ if (isa<CXXRecordDecl>(Decl->getDeclContext())) {
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
+
+ API.createRecord<CXXFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Access, isInSystemHeader(Decl));
+ } else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) {
+ if (RD->isUnion())
+ API.createRecord<UnionFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ else
+ API.createRecord<StructFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ }
+
return true;
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
const CXXConversionDecl *Decl) {
- StringRef Name = API.copyString(Decl->getNameAsString());
- StringRef USR = API.recordUSR(Decl);
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
+ Decl->isImplicit())
+ return true;
+
+ auto Name = Decl->getNameAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1264,19 +1271,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
if (Decl->isStatic())
- API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord<CXXStaticMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Signature, Access, isInSystemHeader(Decl));
else
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord<CXXInstanceMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Signature, Access, isInSystemHeader(Decl));
+
return true;
}
@@ -1291,8 +1296,9 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
if (Method->isPropertyAccessor())
continue;
- StringRef Name = API.copyString(Method->getSelector().getAsString());
- StringRef USR = API.recordUSR(Method);
+ auto Name = Method->getSelector().getAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Method, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Method->getLocation());
DocComment Comment;
@@ -1309,10 +1315,16 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Method);
- API.addObjCMethod(Container, Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Method), Comment,
- Declaration, SubHeading, Signature,
- Method->isInstanceMethod(), isInSystemHeader(Method));
+ if (Method->isInstanceMethod())
+ API.createRecord<ObjCInstanceMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Method), Loc,
+ AvailabilityInfo::createFromDecl(Method), Comment, Declaration,
+ SubHeading, Signature, isInSystemHeader(Method));
+ else
+ API.createRecord<ObjCClassMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Method), Loc,
+ AvailabilityInfo::createFromDecl(Method), Comment, Declaration,
+ SubHeading, Signature, isInSystemHeader(Method));
}
}
@@ -1322,7 +1334,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
const ObjCContainerDecl::prop_range Properties) {
for (const auto *Property : Properties) {
StringRef Name = Property->getName();
- StringRef USR = API.recordUSR(Property);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Property, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Property->getLocation());
DocComment Comment;
@@ -1337,10 +1350,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Property);
- StringRef GetterName =
- API.copyString(Property->getGetterName().getAsString());
- StringRef SetterName =
- API.copyString(Property->getSetterName().getAsString());
+ auto GetterName = Property->getGetterName().getAsString();
+ auto SetterName = Property->getSetterName().getAsString();
// Get the attributes for property.
unsigned Attributes = ObjCPropertyRecord::NoAttr;
@@ -1348,14 +1359,22 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
ObjCPropertyAttribute::kind_readonly)
Attributes |= ObjCPropertyRecord::ReadOnly;
- API.addObjCProperty(
- Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Property),
- Comment, Declaration, SubHeading,
- static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), GetterName,
- SetterName, Property->isOptional(),
- !(Property->getPropertyAttributes() &
- ObjCPropertyAttribute::kind_class),
- isInSystemHeader(Property));
+ if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class)
+ API.createRecord<ObjCClassPropertyRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Property), Loc,
+ AvailabilityInfo::createFromDecl(Property), Comment, Declaration,
+ SubHeading,
+ static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
+ GetterName, SetterName, Property->isOptional(),
+ isInSystemHeader(Property));
+ else
+ API.createRecord<ObjCInstancePropertyRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Property), Loc,
+ AvailabilityInfo::createFromDecl(Property), Comment, Declaration,
+ SubHeading,
+ static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
+ GetterName, SetterName, Property->isOptional(),
+ isInSystemHeader(Property));
}
}
@@ -1367,7 +1386,9 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
Ivars) {
for (const auto *Ivar : Ivars) {
StringRef Name = Ivar->getName();
- StringRef USR = API.recordUSR(Ivar);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Ivar, USR);
+
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
DocComment Comment;
@@ -1382,12 +1403,10 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Ivar);
- ObjCInstanceVariableRecord::AccessControl Access =
- Ivar->getCanonicalAccessControl();
-
- API.addObjCInstanceVariable(
- Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Ivar),
- Comment, Declaration, SubHeading, Access, isInSystemHeader(Ivar));
+ API.createRecord<ObjCInstanceVariableRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Ivar), Loc,
+ AvailabilityInfo::createFromDecl(Ivar), Comment, Declaration,
+ SubHeading, isInSystemHeader(Ivar));
}
}
@@ -1396,8 +1415,7 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProtocols(
ObjCContainerRecord *Container,
ObjCInterfaceDecl::protocol_range Protocols) {
for (const auto *Protocol : Protocols)
- Container->Protocols.emplace_back(Protocol->getName(),
- API.recordUSR(Protocol));
+ Container->Protocols.emplace_back(createSymbolReferenceForDecl(*Protocol));
}
} // namespace impl
diff --git a/clang/include/clang/ExtractAPI/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h
index c67864a..08045a3 100644
--- a/clang/include/clang/ExtractAPI/FrontendActions.h
+++ b/clang/include/clang/ExtractAPI/FrontendActions.h
@@ -49,9 +49,6 @@ private:
void EndSourceFileAction() override;
static StringRef getInputBufferName() { return "<extract-api-includes>"; }
-
- static std::unique_ptr<llvm::raw_pwrite_stream>
- CreateOutputFile(CompilerInstance &CI, StringRef InFile);
};
/// Wrap ExtractAPIAction on top of a pre-existing action
@@ -85,9 +82,6 @@ private:
/// actions. This is the place where all the gathered symbol graph
/// information is emited.
void EndSourceFileAction() override;
-
- static std::unique_ptr<llvm::raw_pwrite_stream>
- CreateOutputFile(CompilerInstance &CI, StringRef InFile);
};
} // namespace clang
diff --git a/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h b/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h
new file mode 100644
index 0000000..07f14f3
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h
@@ -0,0 +1,172 @@
+//===- ExtractAPI/Serialization/APISetVisitor.h ----------------*- 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 ExtractAPI APISetVisitor interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
+#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
+
+#include "clang/ExtractAPI/API.h"
+
+namespace clang {
+namespace extractapi {
+
+// A helper macro to implement short-circuiting when recursing. It
+// invokes CALL_EXPR, which must be a method call, on the derived
+// object (s.t. a user of RecursiveASTVisitor can override the method
+// in CALL_EXPR).
+#define TRY_TO(CALL_EXPR) \
+ do { \
+ if (!getDerived()->CALL_EXPR) \
+ return false; \
+ } while (false)
+
+/// The base interface of visitors for API information, the interface and usage
+/// is almost identical to RecurisveASTVistor. This class performs three
+/// distinct tasks:
+/// 1. traverse the APISet (i.e. go to every record);
+/// 2. at a given record, walk up the class hierarchy starting from the record's
+/// dynamic type until APIRecord is reached.
+/// 3. given a (record, class) combination where 'class' is some base class of
+/// the dynamic type of 'record', call a user-overridable function to actually
+/// visit the record.
+///
+/// These tasks are done by three groups of methods, respectively:
+/// 1. traverseRecord(APIRecord *x) does task #1, it is the entry point for
+/// traversing the records starting from x. This method simply forwards to
+/// traverseFoo(Foo *x) where Foo is the dynamic type of *x, which calls
+/// walkUpFromFoo(x) and then recursively visits the child records of x.
+/// 2. walkUpFromFoo(Foo *x) does task #2. It doesn't visit children records of
+/// x, instead it first calls walkUpFromBar(x) where Bar is the direct parent
+/// class of Foo (unless Foo has no parent) and then calls visitFoo(x).
+/// 3. visitFoo(Foo *x) does task #3.
+///
+/// These three method groups are tiered (traverse* > walkUpFrom* >
+/// visit*). A method (e.g. traverse*) may call methods from the same
+/// tier (e.g. other traverse*) or one tier lower (e.g. walkUpFrom*).
+/// It may not call methods from a higher tier.
+///
+/// Note that since walkUpFromFoo() calls walkUpFromBar() (where Bar
+/// is Foo's super class) before calling visitFoo(), the result is
+/// that the visit*() methods for a given record are called in the
+/// top-down order (e.g. for a record of type ObjCInstancePropertyRecord, the
+/// order will be visitRecord(), visitObjCPropertyRecord(), and then
+/// visitObjCInstancePropertyRecord()).
+///
+/// This scheme guarantees that all visit*() calls for the same record
+/// are grouped together. In other words, visit*() methods for different
+/// records are never interleaved.
+///
+/// Clients of this visitor should subclass the visitor (providing
+/// themselves as the template argument, using the curiously recurring
+/// template pattern) and override any of the traverse*, walkUpFrom*,
+/// and visit* methods for records where the visitor should customize
+/// behavior. Most users only need to override visit*. Advanced
+/// users may override traverse* and walkUpFrom* to implement custom
+/// traversal strategies. Returning false from one of these overridden
+/// functions will abort the entire traversal.
+template <typename Derived> class APISetVisitor {
+public:
+ bool traverseAPISet() {
+ for (const APIRecord *TLR : API.getTopLevelRecords()) {
+ TRY_TO(traverseAPIRecord(TLR));
+ }
+ return true;
+ }
+
+ bool traverseAPIRecord(const APIRecord *Record);
+ bool walkUpFromAPIRecord(const APIRecord *Record) {
+ TRY_TO(visitAPIRecord(Record));
+ return true;
+ }
+ bool visitAPIRecord(const APIRecord *Record) { return true; }
+
+#define GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
+ bool traverse##CLASS(const CLASS *Record) { \
+ TRY_TO(walkUpFrom##CLASS(Record)); \
+ TRY_TO(traverseRecordContext(dyn_cast<RecordContext>(Record))); \
+ return true; \
+ }
+
+#define GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) \
+ bool walkUpFrom##CLASS(const CLASS *Record) { \
+ TRY_TO(walkUpFrom##BASE(Record)); \
+ TRY_TO(visit##CLASS(Record)); \
+ return true; \
+ } \
+ bool visit##CLASS(const CLASS *Record) { return true; }
+
+#define CONCRETE_RECORD(CLASS, BASE, KIND) \
+ GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
+ GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
+
+#define ABSTRACT_RECORD(CLASS, BASE) \
+ GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
+
+#include "../APIRecords.inc"
+
+#undef GENERATE_WALKUP_AND_VISIT_METHODS
+#undef GENERATE_TRAVERSE_METHOD
+
+ bool traverseRecordContext(const RecordContext *);
+
+protected:
+ const APISet &API;
+
+public:
+ APISetVisitor() = delete;
+ APISetVisitor(const APISetVisitor &) = delete;
+ APISetVisitor(APISetVisitor &&) = delete;
+ APISetVisitor &operator=(const APISetVisitor &) = delete;
+ APISetVisitor &operator=(APISetVisitor &&) = delete;
+
+protected:
+ APISetVisitor(const APISet &API) : API(API) {}
+ ~APISetVisitor() = default;
+
+ Derived *getDerived() { return static_cast<Derived *>(this); };
+};
+
+template <typename Derived>
+bool APISetVisitor<Derived>::traverseRecordContext(
+ const RecordContext *Context) {
+ if (!Context)
+ return true;
+
+ for (auto *Child : Context->records())
+ TRY_TO(traverseAPIRecord(Child));
+
+ return true;
+}
+
+template <typename Derived>
+bool APISetVisitor<Derived>::traverseAPIRecord(const APIRecord *Record) {
+ switch (Record->getKind()) {
+#define CONCRETE_RECORD(CLASS, BASE, KIND) \
+ case APIRecord::KIND: { \
+ TRY_TO(traverse##CLASS(static_cast<const CLASS *>(Record))); \
+ break; \
+ }
+#include "../APIRecords.inc"
+ case APIRecord::RK_Unknown: {
+ TRY_TO(walkUpFromAPIRecord(static_cast<const APIRecord *>(Record)));
+ break;
+ }
+ default:
+ llvm_unreachable("API Record with uninstantiable kind");
+ }
+ return true;
+}
+
+} // namespace extractapi
+} // namespace clang
+
+#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
diff --git a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
deleted file mode 100644
index f0629a9..0000000
--- a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
+++ /dev/null
@@ -1,314 +0,0 @@
-//===- ExtractAPI/Serialization/SerializerBase.h ----------------*- 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 ExtractAPI APISetVisitor interface.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
-#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
-
-#include "clang/ExtractAPI/API.h"
-
-namespace clang {
-namespace extractapi {
-
-/// The base interface of visitors for API information.
-template <typename Derived> class APISetVisitor {
-public:
- void traverseAPISet() {
- getDerived()->traverseNamespaces();
-
- getDerived()->traverseGlobalVariableRecords();
-
- getDerived()->traverseGlobalFunctionRecords();
-
- getDerived()->traverseEnumRecords();
-
- getDerived()->traverseStaticFieldRecords();
-
- getDerived()->traverseCXXClassRecords();
-
- getDerived()->traverseClassTemplateRecords();
-
- getDerived()->traverseClassTemplateSpecializationRecords();
-
- getDerived()->traverseClassTemplatePartialSpecializationRecords();
-
- getDerived()->traverseCXXInstanceMethods();
-
- getDerived()->traverseCXXStaticMethods();
-
- getDerived()->traverseCXXMethodTemplates();
-
- getDerived()->traverseCXXMethodTemplateSpecializations();
-
- getDerived()->traverseCXXFields();
-
- getDerived()->traverseCXXFieldTemplates();
-
- getDerived()->traverseConcepts();
-
- getDerived()->traverseGlobalVariableTemplateRecords();
-
- getDerived()->traverseGlobalVariableTemplateSpecializationRecords();
-
- getDerived()->traverseGlobalVariableTemplatePartialSpecializationRecords();
-
- getDerived()->traverseGlobalFunctionTemplateRecords();
-
- getDerived()->traverseGlobalFunctionTemplateSpecializationRecords();
-
- getDerived()->traverseRecordRecords();
-
- getDerived()->traverseObjCInterfaces();
-
- getDerived()->traverseObjCProtocols();
-
- getDerived()->traverseObjCCategories();
-
- getDerived()->traverseMacroDefinitionRecords();
-
- getDerived()->traverseTypedefRecords();
- }
-
- void traverseNamespaces() {
- for (const auto &Namespace : API.getNamespaces())
- getDerived()->visitNamespaceRecord(*Namespace.second);
- }
-
- void traverseGlobalFunctionRecords() {
- for (const auto &GlobalFunction : API.getGlobalFunctions())
- getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second);
- }
-
- void traverseGlobalVariableRecords() {
- for (const auto &GlobalVariable : API.getGlobalVariables())
- getDerived()->visitGlobalVariableRecord(*GlobalVariable.second);
- }
-
- void traverseEnumRecords() {
- for (const auto &Enum : API.getEnums())
- getDerived()->visitEnumRecord(*Enum.second);
- }
-
- void traverseRecordRecords() {
- for (const auto &Record : API.getRecords())
- getDerived()->visitRecordRecord(*Record.second);
- }
-
- void traverseStaticFieldRecords() {
- for (const auto &StaticField : API.getStaticFields())
- getDerived()->visitStaticFieldRecord(*StaticField.second);
- }
-
- void traverseCXXClassRecords() {
- for (const auto &Class : API.getCXXClasses())
- getDerived()->visitCXXClassRecord(*Class.second);
- }
-
- void traverseCXXMethodTemplates() {
- for (const auto &MethodTemplate : API.getCXXMethodTemplates())
- getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
- }
-
- void traverseCXXMethodTemplateSpecializations() {
- for (const auto &MethodTemplateSpecialization :
- API.getCXXMethodTemplateSpecializations())
- getDerived()->visitMethodTemplateSpecializationRecord(
- *MethodTemplateSpecialization.second);
- }
-
- void traverseClassTemplateRecords() {
- for (const auto &ClassTemplate : API.getClassTemplates())
- getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
- }
-
- void traverseClassTemplateSpecializationRecords() {
- for (const auto &ClassTemplateSpecialization :
- API.getClassTemplateSpecializations())
- getDerived()->visitClassTemplateSpecializationRecord(
- *ClassTemplateSpecialization.second);
- }
-
- void traverseClassTemplatePartialSpecializationRecords() {
- for (const auto &ClassTemplatePartialSpecialization :
- API.getClassTemplatePartialSpecializations())
- getDerived()->visitClassTemplatePartialSpecializationRecord(
- *ClassTemplatePartialSpecialization.second);
- }
-
- void traverseCXXInstanceMethods() {
- for (const auto &InstanceMethod : API.getCXXInstanceMethods())
- getDerived()->visitCXXInstanceMethodRecord(*InstanceMethod.second);
- }
-
- void traverseCXXStaticMethods() {
- for (const auto &InstanceMethod : API.getCXXStaticMethods())
- getDerived()->visitCXXStaticMethodRecord(*InstanceMethod.second);
- }
-
- void traverseCXXFields() {
- for (const auto &CXXField : API.getCXXFields())
- getDerived()->visitCXXFieldRecord(*CXXField.second);
- }
-
- void traverseCXXFieldTemplates() {
- for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates())
- getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second);
- }
-
- void traverseGlobalVariableTemplateRecords() {
- for (const auto &GlobalVariableTemplate : API.getGlobalVariableTemplates())
- getDerived()->visitGlobalVariableTemplateRecord(
- *GlobalVariableTemplate.second);
- }
-
- void traverseGlobalVariableTemplateSpecializationRecords() {
- for (const auto &GlobalVariableTemplateSpecialization :
- API.getGlobalVariableTemplateSpecializations())
- getDerived()->visitGlobalVariableTemplateSpecializationRecord(
- *GlobalVariableTemplateSpecialization.second);
- }
-
- void traverseGlobalVariableTemplatePartialSpecializationRecords() {
- for (const auto &GlobalVariableTemplatePartialSpecialization :
- API.getGlobalVariableTemplatePartialSpecializations())
- getDerived()->visitGlobalVariableTemplatePartialSpecializationRecord(
- *GlobalVariableTemplatePartialSpecialization.second);
- }
-
- void traverseGlobalFunctionTemplateRecords() {
- for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
- getDerived()->visitGlobalFunctionTemplateRecord(
- *GlobalFunctionTemplate.second);
- }
-
- void traverseGlobalFunctionTemplateSpecializationRecords() {
- for (const auto &GlobalFunctionTemplateSpecialization :
- API.getGlobalFunctionTemplateSpecializations())
- getDerived()->visitGlobalFunctionTemplateSpecializationRecord(
- *GlobalFunctionTemplateSpecialization.second);
- }
-
- void traverseConcepts() {
- for (const auto &Concept : API.getConcepts())
- getDerived()->visitConceptRecord(*Concept.second);
- }
-
- void traverseObjCInterfaces() {
- for (const auto &Interface : API.getObjCInterfaces())
- getDerived()->visitObjCContainerRecord(*Interface.second);
- }
-
- void traverseObjCProtocols() {
- for (const auto &Protocol : API.getObjCProtocols())
- getDerived()->visitObjCContainerRecord(*Protocol.second);
- }
-
- void traverseObjCCategories() {
- for (const auto &Category : API.getObjCCategories())
- getDerived()->visitObjCCategoryRecord(*Category.second);
- }
-
- void traverseMacroDefinitionRecords() {
- for (const auto &Macro : API.getMacros())
- getDerived()->visitMacroDefinitionRecord(*Macro.second);
- }
-
- void traverseTypedefRecords() {
- for (const auto &Typedef : API.getTypedefs())
- getDerived()->visitTypedefRecord(*Typedef.second);
- }
-
- void visitNamespaceRecord(const NamespaceRecord &Record){};
-
- /// Visit a global function record.
- void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){};
-
- /// Visit a global variable record.
- void visitGlobalVariableRecord(const GlobalVariableRecord &Record){};
-
- /// Visit an enum record.
- void visitEnumRecord(const EnumRecord &Record){};
-
- /// Visit a record record.
- void visitRecordRecord(const RecordRecord &Record){};
-
- void visitStaticFieldRecord(const StaticFieldRecord &Record){};
-
- void visitCXXClassRecord(const CXXClassRecord &Record){};
-
- void visitClassTemplateRecord(const ClassTemplateRecord &Record){};
-
- void visitClassTemplateSpecializationRecord(
- const ClassTemplateSpecializationRecord &Record){};
-
- void visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord &Record){};
-
- void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){};
-
- void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){};
-
- void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
-
- void visitMethodTemplateSpecializationRecord(
- const CXXMethodTemplateSpecializationRecord &Record){};
-
- void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record){};
-
- void visitGlobalVariableTemplateRecord(
- const GlobalVariableTemplateRecord &Record) {}
-
- void visitGlobalVariableTemplateSpecializationRecord(
- const GlobalVariableTemplateSpecializationRecord &Record){};
-
- void visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord &Record){};
-
- void visitGlobalFunctionTemplateRecord(
- const GlobalFunctionTemplateRecord &Record){};
-
- void visitGlobalFunctionTemplateSpecializationRecord(
- const GlobalFunctionTemplateSpecializationRecord &Record){};
-
- /// Visit an Objective-C container record.
- void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
-
- /// Visit an Objective-C category record.
- void visitObjCCategoryRecord(const ObjCCategoryRecord &Record){};
-
- /// Visit a macro definition record.
- void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record){};
-
- /// Visit a typedef record.
- void visitTypedefRecord(const TypedefRecord &Record){};
-
-protected:
- const APISet &API;
-
-public:
- APISetVisitor() = delete;
- APISetVisitor(const APISetVisitor &) = delete;
- APISetVisitor(APISetVisitor &&) = delete;
- APISetVisitor &operator=(const APISetVisitor &) = delete;
- APISetVisitor &operator=(APISetVisitor &&) = delete;
-
-protected:
- APISetVisitor(const APISet &API) : API(API) {}
- ~APISetVisitor() = default;
-
- Derived *getDerived() { return static_cast<Derived *>(this); };
-};
-
-} // namespace extractapi
-} // namespace clang
-
-#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
index 4249ac4..724b087 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -17,11 +17,17 @@
#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
+#include "clang/Basic/Module.h"
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
-#include "clang/ExtractAPI/Serialization/SerializerBase.h"
+#include "clang/ExtractAPI/Serialization/APISetVisitor.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
@@ -35,7 +41,30 @@ using namespace llvm::json;
/// Common options to customize the visitor output.
struct SymbolGraphSerializerOption {
/// Do not include unnecessary whitespaces to save space.
- bool Compact;
+ bool Compact = true;
+ bool EmitSymbolLabelsForTesting = false;
+};
+
+/// A representation of the contents of a given module symbol graph
+struct ExtendedModule {
+ ExtendedModule() = default;
+ ExtendedModule(ExtendedModule &&EM) = default;
+ ExtendedModule &operator=(ExtendedModule &&EM) = default;
+ // Copies are expensive so disable them.
+ ExtendedModule(const ExtendedModule &EM) = delete;
+ ExtendedModule &operator=(const ExtendedModule &EM) = delete;
+
+ /// Add a symbol to the module, do not store the resulting pointer or use it
+ /// across insertions.
+ Object *addSymbol(Object &&Symbol);
+
+ void addRelationship(Object &&Relationship);
+
+ /// A JSON array of formatted symbols from an \c APISet.
+ Array Symbols;
+
+ /// A JSON array of formatted symbol relationships from an \c APISet.
+ Array Relationships;
};
/// The visitor that organizes API information in the Symbol Graph format.
@@ -44,28 +73,54 @@ struct SymbolGraphSerializerOption {
/// models an API set as a directed graph, where nodes are symbol declarations,
/// and edges are relationships between the connected symbols.
class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
- /// A JSON array of formatted symbols in \c APISet.
- Array Symbols;
+private:
+ using Base = APISetVisitor<SymbolGraphSerializer>;
+ /// The main symbol graph that contains symbols that are either top-level or a
+ /// are related to symbols defined in this product/module.
+ ExtendedModule MainModule;
- /// A JSON array of formatted symbol relationships in \c APISet.
- Array Relationships;
+ /// Additional symbol graphs that contain symbols that are related to symbols
+ /// defined in another product/module. The key of this map is the module name
+ /// of the extended module.
+ llvm::StringMap<ExtendedModule> ExtendedModules;
/// The Symbol Graph format version used by this serializer.
static const VersionTuple FormatVersion;
- /// Indicates whether child symbols should be visited. This is mainly
+ /// Indicates whether to take into account the extended module. This is only
/// useful for \c serializeSingleSymbolSGF.
- bool ShouldRecurse;
+ bool ForceEmitToMainModule;
-public:
- /// Serialize the APIs in \c APISet in the Symbol Graph format.
+ // Stores the references required to construct path components for the
+ // currently visited APIRecord.
+ llvm::SmallVector<SymbolReference, 8> Hierarchy;
+
+ /// The list of symbols to ignore.
///
- /// \returns a JSON object that contains the root of the formatted
- /// Symbol Graph.
- Object serialize();
+ /// Note: This should be consulted before emitting a symbol.
+ const APIIgnoresList &IgnoresList;
- /// Wrap serialize(void) and write out the serialized JSON object to \p os.
- void serialize(raw_ostream &os);
+ const bool EmitSymbolLabelsForTesting = false;
+
+ /// The object instantiated by the last call to serializeAPIRecord.
+ Object *CurrentSymbol = nullptr;
+
+ /// The module to which \p CurrentSymbol belongs too.
+ ExtendedModule *ModuleForCurrentSymbol = nullptr;
+
+public:
+ static void
+ serializeMainSymbolGraph(raw_ostream &OS, const APISet &API,
+ const APIIgnoresList &IgnoresList,
+ SymbolGraphSerializerOption Options = {});
+
+ static void serializeWithExtensionGraphs(
+ raw_ostream &MainOutput, const APISet &API,
+ const APIIgnoresList &IgnoresList,
+ llvm::function_ref<
+ std::unique_ptr<llvm::raw_pwrite_stream>(llvm::Twine BaseFileName)>
+ CreateOutputStream,
+ SymbolGraphSerializerOption Options = {});
/// Serialize a single symbol SGF. This is primarily used for libclang.
///
@@ -75,6 +130,7 @@ public:
static std::optional<Object> serializeSingleSymbolSGF(StringRef USR,
const APISet &API);
+private:
/// The kind of a relationship between two symbols.
enum RelationshipKind {
/// The source symbol is a member of the target symbol.
@@ -94,16 +150,32 @@ public:
ExtensionTo,
};
+ /// Serialize a single record.
+ void serializeSingleRecord(const APIRecord *Record);
+
/// Get the string representation of the relationship kind.
static StringRef getRelationshipString(RelationshipKind Kind);
+ void serializeRelationship(RelationshipKind Kind,
+ const SymbolReference &Source,
+ const SymbolReference &Target,
+ ExtendedModule &Into);
+
enum ConstraintKind { Conformance, ConditionalConformance };
static StringRef getConstraintString(ConstraintKind Kind);
-private:
- /// Just serialize the currently recorded objects in Symbol Graph format.
- Object serializeCurrentGraph();
+ /// Serialize the APIs in \c ExtendedModule.
+ ///
+ /// \returns a JSON object that contains the root of the formatted
+ /// Symbol Graph.
+ Object serializeGraph(StringRef ModuleName, ExtendedModule &&EM);
+
+ /// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and
+ /// write them to the provide stream.
+ void serializeGraphToStream(raw_ostream &OS,
+ SymbolGraphSerializerOption Options,
+ StringRef ModuleName, ExtendedModule &&EM);
/// Synthesize the metadata section of the Symbol Graph format.
///
@@ -117,124 +189,92 @@ private:
/// by the given API set.
/// Note that "module" here is not to be confused with the Clang/C++ module
/// concept.
- Object serializeModule() const;
+ Object serializeModuleObject(StringRef ModuleName) const;
+
+ Array serializePathComponents(const APIRecord *Record) const;
/// Determine if the given \p Record should be skipped during serialization.
- bool shouldSkip(const APIRecord &Record) const;
+ bool shouldSkip(const APIRecord *Record) const;
+
+ ExtendedModule &getModuleForCurrentSymbol();
/// Format the common API information for \p Record.
///
/// This handles the shared information of all kinds of API records,
- /// for example identifier and source location. The resulting object is then
- /// augmented with kind-specific symbol information by the caller.
- /// This method also checks if the given \p Record should be skipped during
- /// serialization.
+ /// for example identifier, source location and path components. The resulting
+ /// object is then augmented with kind-specific symbol information in
+ /// subsequent visit* methods by accessing the \p State member variable. This
+ /// method also checks if the given \p Record should be skipped during
+ /// serialization. This should be called only once per concrete APIRecord
+ /// instance and the first visit* method to be called is responsible for
+ /// calling this. This is normally visitAPIRecord unless a walkUpFromFoo
+ /// method is implemented along the inheritance hierarchy in which case the
+ /// visitFoo method needs to call this.
///
- /// \returns \c std::nullopt if this \p Record should be skipped, or a JSON
- /// object containing common symbol information of \p Record.
- template <typename RecordTy>
- std::optional<Object> serializeAPIRecord(const RecordTy &Record) const;
-
- /// Helper method to serialize second-level member records of \p Record and
- /// the member-of relationships.
- template <typename MemberTy>
- void serializeMembers(const APIRecord &Record,
- const SmallVector<std::unique_ptr<MemberTy>> &Members);
-
- /// Serialize the \p Kind relationship between \p Source and \p Target.
- ///
- /// Record the relationship between the two symbols in
- /// SymbolGraphSerializer::Relationships.
- void serializeRelationship(RelationshipKind Kind, SymbolReference Source,
- SymbolReference Target);
-
-protected:
- /// The list of symbols to ignore.
- ///
- /// Note: This should be consulted before emitting a symbol.
- const APIIgnoresList &IgnoresList;
-
- SymbolGraphSerializerOption Options;
-
- llvm::StringSet<> visitedCategories;
+ /// \returns \c nullptr if this \p Record should be skipped, or a pointer to
+ /// JSON object containing common symbol information of \p Record. Do not
+ /// store the returned pointer only use it to augment the object with record
+ /// specific information as it directly points to the object in the
+ /// \p ExtendedModule, the pointer won't be valid as soon as another object is
+ /// inserted into the module.
+ void serializeAPIRecord(const APIRecord *Record);
public:
- void visitNamespaceRecord(const NamespaceRecord &Record);
-
- /// Visit a global function record.
- void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record);
-
- /// Visit a global variable record.
- void visitGlobalVariableRecord(const GlobalVariableRecord &Record);
-
- /// Visit an enum record.
- void visitEnumRecord(const EnumRecord &Record);
-
- /// Visit a record record.
- void visitRecordRecord(const RecordRecord &Record);
-
- void visitStaticFieldRecord(const StaticFieldRecord &Record);
+ // Handle if records should be skipped at this level of the traversal to
+ // ensure that children of skipped records aren't serialized.
+ bool traverseAPIRecord(const APIRecord *Record);
- void visitCXXClassRecord(const CXXClassRecord &Record);
+ bool visitAPIRecord(const APIRecord *Record);
- void visitClassTemplateRecord(const ClassTemplateRecord &Record);
-
- void visitClassTemplateSpecializationRecord(
- const ClassTemplateSpecializationRecord &Record);
-
- void visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord &Record);
-
- void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record);
+ /// Visit a global function record.
+ bool visitGlobalFunctionRecord(const GlobalFunctionRecord *Record);
- void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record);
+ bool visitCXXClassRecord(const CXXClassRecord *Record);
- void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
+ bool visitClassTemplateRecord(const ClassTemplateRecord *Record);
- void visitMethodTemplateSpecializationRecord(
- const CXXMethodTemplateSpecializationRecord &Record);
+ bool visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord *Record);
- void visitCXXFieldRecord(const CXXFieldRecord &Record);
+ bool visitCXXMethodRecord(const CXXMethodRecord *Record);
- void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
+ bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record);
- void visitConceptRecord(const ConceptRecord &Record);
+ bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record);
- void
- visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord &Record);
+ bool visitConceptRecord(const ConceptRecord *Record);
- void visitGlobalVariableTemplateSpecializationRecord(
- const GlobalVariableTemplateSpecializationRecord &Record);
+ bool
+ visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record);
- void visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord &Record);
+ bool visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord *Record);
- void
- visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
+ bool
+ visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record);
- void visitGlobalFunctionTemplateSpecializationRecord(
- const GlobalFunctionTemplateSpecializationRecord &Record);
+ bool visitObjCContainerRecord(const ObjCContainerRecord *Record);
- /// Visit an Objective-C container record.
- void visitObjCContainerRecord(const ObjCContainerRecord &Record);
+ bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record);
- /// Visit an Objective-C category record.
- void visitObjCCategoryRecord(const ObjCCategoryRecord &Record);
+ bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record);
+ bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record);
+ bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record);
- /// Visit a macro definition record.
- void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record);
+ bool visitObjCMethodRecord(const ObjCMethodRecord *Record);
- /// Visit a typedef record.
- void visitTypedefRecord(const TypedefRecord &Record);
+ bool
+ visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record);
- /// Serialize a single record.
- void serializeSingleRecord(const APIRecord *Record);
+ bool walkUpFromTypedefRecord(const TypedefRecord *Record);
+ bool visitTypedefRecord(const TypedefRecord *Record);
SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList,
- SymbolGraphSerializerOption Options = {},
- bool ShouldRecurse = true)
- : APISetVisitor(API), ShouldRecurse(ShouldRecurse),
- IgnoresList(IgnoresList), Options(Options) {}
+ bool EmitSymbolLabelsForTesting = false,
+ bool ForceEmitToMainModule = false)
+ : Base(API), ForceEmitToMainModule(ForceEmitToMainModule),
+ IgnoresList(IgnoresList),
+ EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {}
};
} // namespace extractapi
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 8085dbc..5ee4d47 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -15,6 +15,7 @@
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cassert>
#include <map>
@@ -387,6 +388,22 @@ public:
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesShareFileManager : 1;
+ /// Whether to emit symbol graph files as a side effect of compilation.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitSymbolGraph : 1;
+
+ /// Whether to emit additional symbol graphs for extended modules.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitExtensionSymbolGraphs : 1;
+
+ /// Whether to emit symbol labels for testing in generated symbol graphs
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitSymbolGraphSymbolLabelsForTesting : 1;
+
+ /// Whether to emit symbol labels for testing in generated symbol graphs
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitPrettySymbolGraphs : 1;
+
CodeCompleteOptions CodeCompleteOpts;
/// Specifies the output format of the AST.
@@ -496,10 +513,8 @@ public:
// ignore when extracting documentation.
std::vector<std::string> ExtractAPIIgnoresFileList;
- // Currently this is only used as part of the `-emit-symbol-graph`
- // action.
// Location of output directory where symbol graph information would
- // be dumped
+ // be dumped. This overrides regular -o output file specification
std::string SymbolGraphOutputDir;
/// Args to pass to the plugins
@@ -565,7 +580,9 @@ public:
BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
IncludeTimestamps(true), UseTemporary(true),
AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true),
- TimeTraceGranularity(500) {}
+ EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false),
+ EmitSymbolGraphSymbolLabelsForTesting(false),
+ EmitPrettySymbolGraphs(false), TimeTraceGranularity(500) {}
/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C.
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index f31efa5..f762116 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -41,7 +41,7 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
-const unsigned VERSION_MAJOR = 29;
+const unsigned VERSION_MAJOR = 30;
/// AST file minor version number supported by this version of
/// Clang.
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 3ed9803..214eb36 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -542,6 +542,7 @@ private:
void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
+ void WriteDeclAndTypes(ASTContext &Context);
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
@@ -846,7 +847,7 @@ private:
/// AST and semantic-analysis consumer that generates a
/// precompiled header from the parsed source code.
class PCHGenerator : public SemaConsumer {
- const Preprocessor &PP;
+ Preprocessor &PP;
std::string OutputFile;
std::string isysroot;
Sema *SemaPtr;
@@ -867,11 +868,12 @@ protected:
DiagnosticsEngine &getDiagnostics() const {
return SemaPtr->getDiagnostics();
}
+ Preprocessor &getPreprocessor() { return PP; }
virtual Module *getEmittingModule(ASTContext &Ctx);
public:
- PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+ PCHGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
StringRef OutputFile, StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
@@ -893,7 +895,7 @@ protected:
virtual Module *getEmittingModule(ASTContext &Ctx) override;
public:
- ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+ ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
StringRef OutputFile);
void HandleTranslationUnit(ASTContext &Ctx) override;
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 94a47a8..45d4c96 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -4541,6 +4541,10 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
ToVar->setQualifierInfo(ToQualifierLoc);
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
+ if (D->isInlineSpecified())
+ ToVar->setInlineSpecified();
+ if (D->isInline())
+ ToVar->setImplicitlyInline();
if (FoundByLookup) {
auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl());
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 2cbb86b31..66a727d 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1852,9 +1852,9 @@ DeclContext::lookup(DeclarationName Name) const {
DeclContext::lookup_result
DeclContext::noload_lookup(DeclarationName Name) {
- assert(getDeclKind() != Decl::LinkageSpec &&
- getDeclKind() != Decl::Export &&
- "should not perform lookups into transparent contexts");
+ // For transparent DeclContext, we should lookup in their enclosing context.
+ if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export)
+ return getParent()->noload_lookup(Name);
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 9d551ff..075c8aba 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1746,14 +1746,15 @@ void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
static void printCountAttributedImpl(const CountAttributedType *T,
raw_ostream &OS,
const PrintingPolicy &Policy) {
+ OS << ' ';
if (T->isCountInBytes() && T->isOrNull())
- OS << " __sized_by_or_null(";
+ OS << "__sized_by_or_null(";
else if (T->isCountInBytes())
- OS << " __sized_by(";
+ OS << "__sized_by(";
else if (T->isOrNull())
- OS << " __counted_by_or_null(";
+ OS << "__counted_by_or_null(";
else
- OS << " __counted_by(";
+ OS << "__counted_by(";
if (T->getCountExpr())
T->getCountExpr()->printPretty(OS, nullptr, Policy);
OS << ')';
@@ -1762,14 +1763,14 @@ static void printCountAttributedImpl(const CountAttributedType *T,
void TypePrinter::printCountAttributedBefore(const CountAttributedType *T,
raw_ostream &OS) {
printBefore(T->desugar(), OS);
- if (!T->desugar()->isArrayType())
+ if (!T->isArrayType())
printCountAttributedImpl(T, OS, Policy);
}
void TypePrinter::printCountAttributedAfter(const CountAttributedType *T,
raw_ostream &OS) {
printAfter(T->desugar(), OS);
- if (T->desugar()->isArrayType())
+ if (T->isArrayType())
printCountAttributedImpl(T, OS, Policy);
}
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index f729d67..70ac076 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -166,17 +166,16 @@ static Value *joinDistinctValues(QualType Type, Value &Val1,
return JoinedVal;
}
-// When widening does not change `Current`, return value will equal `&Prev`.
-static Value &widenDistinctValues(QualType Type, Value &Prev,
- const Environment &PrevEnv, Value &Current,
- Environment &CurrentEnv,
- Environment::ValueModel &Model) {
+static WidenResult widenDistinctValues(QualType Type, Value &Prev,
+ const Environment &PrevEnv,
+ Value &Current, Environment &CurrentEnv,
+ Environment::ValueModel &Model) {
// Boolean-model widening.
if (auto *PrevBool = dyn_cast<BoolValue>(&Prev)) {
- // If previous value was already Top, re-use that to (implicitly) indicate
- // that no change occurred.
if (isa<TopBoolValue>(Prev))
- return Prev;
+ // Safe to return `Prev` here, because Top is never dependent on the
+ // environment.
+ return {&Prev, LatticeEffect::Unchanged};
// We may need to widen to Top, but before we do so, check whether both
// values are implied to be either true or false in the current environment.
@@ -185,22 +184,24 @@ static Value &widenDistinctValues(QualType Type, Value &Prev,
bool TruePrev = PrevEnv.proves(PrevBool->formula());
bool TrueCur = CurrentEnv.proves(CurBool.formula());
if (TruePrev && TrueCur)
- return CurrentEnv.getBoolLiteralValue(true);
+ return {&CurrentEnv.getBoolLiteralValue(true), LatticeEffect::Unchanged};
if (!TruePrev && !TrueCur &&
PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool->formula())) &&
CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula())))
- return CurrentEnv.getBoolLiteralValue(false);
+ return {&CurrentEnv.getBoolLiteralValue(false), LatticeEffect::Unchanged};
- return CurrentEnv.makeTopBoolValue();
+ return {&CurrentEnv.makeTopBoolValue(), LatticeEffect::Changed};
}
// FIXME: Add other built-in model widening.
// Custom-model widening.
- if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
- return *W;
+ if (auto Result = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
+ return *Result;
- return equateUnknownValues(Prev.getKind()) ? Prev : Current;
+ return {&Current, equateUnknownValues(Prev.getKind())
+ ? LatticeEffect::Unchanged
+ : LatticeEffect::Changed};
}
// Returns whether the values in `Map1` and `Map2` compare equal for those
@@ -271,7 +272,7 @@ llvm::MapVector<Key, Value *>
widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
const llvm::MapVector<Key, Value *> &PrevMap,
Environment &CurEnv, const Environment &PrevEnv,
- Environment::ValueModel &Model, LatticeJoinEffect &Effect) {
+ Environment::ValueModel &Model, LatticeEffect &Effect) {
llvm::MapVector<Key, Value *> WidenedMap;
for (auto &Entry : CurMap) {
Key K = Entry.first;
@@ -290,11 +291,11 @@ widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
continue;
}
- Value &WidenedVal = widenDistinctValues(K->getType(), *PrevIt->second,
- PrevEnv, *Val, CurEnv, Model);
- WidenedMap.insert({K, &WidenedVal});
- if (&WidenedVal != PrevIt->second)
- Effect = LatticeJoinEffect::Changed;
+ auto [WidenedVal, ValEffect] = widenDistinctValues(
+ K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model);
+ WidenedMap.insert({K, WidenedVal});
+ if (ValEffect == LatticeEffect::Changed)
+ Effect = LatticeEffect::Changed;
}
return WidenedMap;
@@ -617,15 +618,15 @@ bool Environment::equivalentTo(const Environment &Other,
return true;
}
-LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
- Environment::ValueModel &Model) {
+LatticeEffect Environment::widen(const Environment &PrevEnv,
+ Environment::ValueModel &Model) {
assert(DACtx == PrevEnv.DACtx);
assert(ReturnVal == PrevEnv.ReturnVal);
assert(ReturnLoc == PrevEnv.ReturnLoc);
assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
assert(CallStack == PrevEnv.CallStack);
- auto Effect = LatticeJoinEffect::Unchanged;
+ auto Effect = LatticeEffect::Unchanged;
// By the API, `PrevEnv` is a previous version of the environment for the same
// block, so we have some guarantees about its shape. In particular, it will
@@ -646,7 +647,7 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
ExprToVal.size() != PrevEnv.ExprToVal.size() ||
LocToVal.size() != PrevEnv.LocToVal.size())
- Effect = LatticeJoinEffect::Changed;
+ Effect = LatticeEffect::Changed;
return Effect;
}
diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h
index c9dcf43..0d6e4b4 100644
--- a/clang/lib/Basic/Targets/Mips.h
+++ b/clang/lib/Basic/Targets/Mips.h
@@ -318,6 +318,7 @@ public:
FPMode = isFP64Default() ? FP64 : FPXX;
NoOddSpreg = false;
bool OddSpregGiven = false;
+ bool StrictAlign = false;
for (const auto &Feature : Features) {
if (Feature == "+single-float")
@@ -330,6 +331,10 @@ public:
IsMicromips = true;
else if (Feature == "+mips32r6" || Feature == "+mips64r6")
HasUnalignedAccess = true;
+ // We cannot be sure that the order of strict-align vs mips32r6.
+ // Thus we need an extra variable here.
+ else if (Feature == "+strict-align")
+ StrictAlign = true;
else if (Feature == "+dsp")
DspRev = std::max(DspRev, DSP1);
else if (Feature == "+dspr2")
@@ -368,6 +373,9 @@ public:
if (FPMode == FPXX && !OddSpregGiven)
NoOddSpreg = true;
+ if (StrictAlign)
+ HasUnalignedAccess = false;
+
setDataLayout();
return true;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 4899c9b..ee4bd80 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -99,9 +99,6 @@ using namespace llvm;
namespace llvm {
extern cl::opt<bool> PrintPipelinePasses;
-static cl::opt<bool> ClRemoveTraps("clang-remove-traps", cl::Optional,
- cl::desc("Insert remove-traps pass."));
-
// Experiment to move sanitizers earlier.
static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
"sanitizer-early-opt-ep", cl::Optional,
@@ -749,7 +746,7 @@ static void addSanitizers(const Triple &TargetTriple,
PB.registerOptimizerLastEPCallback(SanitizersCallback);
}
- if (ClRemoveTraps) {
+ if (RemoveTrapsPass::IsRequested()) {
// We can optimize after inliner, and PGO profile matching. The hook below
// is called at the end `buildFunctionSimplificationPipeline`, which called
// from `buildInlinerPipeline`, which called after profile matching.
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index a01f2c7..47f063b 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -962,7 +962,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
}
// If it's a reference variable, copy the reference into the block field.
- } else if (auto refType = type->getAs<ReferenceType>()) {
+ } else if (type->getAs<ReferenceType>()) {
Builder.CreateStore(src.emitRawPointer(*this), blockField);
// If type is const-qualified, copy the value into the block field.
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 483f9c2..2537e71 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -7281,8 +7281,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vabdq_f16, NEON::BI__builtin_neon_vabdq_v, },
{ NEON::BI__builtin_neon_vabs_f16, NEON::BI__builtin_neon_vabs_v, },
{ NEON::BI__builtin_neon_vabsq_f16, NEON::BI__builtin_neon_vabsq_v, },
- { NEON::BI__builtin_neon_vbsl_f16, NEON::BI__builtin_neon_vbsl_v, },
- { NEON::BI__builtin_neon_vbslq_f16, NEON::BI__builtin_neon_vbslq_v, },
{ NEON::BI__builtin_neon_vcage_f16, NEON::BI__builtin_neon_vcage_v, },
{ NEON::BI__builtin_neon_vcageq_f16, NEON::BI__builtin_neon_vcageq_v, },
{ NEON::BI__builtin_neon_vcagt_f16, NEON::BI__builtin_neon_vcagt_v, },
@@ -7301,8 +7299,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vclezq_f16, NEON::BI__builtin_neon_vclezq_v, },
{ NEON::BI__builtin_neon_vcltz_f16, NEON::BI__builtin_neon_vcltz_v, },
{ NEON::BI__builtin_neon_vcltzq_f16, NEON::BI__builtin_neon_vcltzq_v, },
- { NEON::BI__builtin_neon_vext_f16, NEON::BI__builtin_neon_vext_v, },
- { NEON::BI__builtin_neon_vextq_f16, NEON::BI__builtin_neon_vextq_v, },
{ NEON::BI__builtin_neon_vfma_f16, NEON::BI__builtin_neon_vfma_v, },
{ NEON::BI__builtin_neon_vfma_lane_f16, NEON::BI__builtin_neon_vfma_lane_v, },
{ NEON::BI__builtin_neon_vfma_laneq_f16, NEON::BI__builtin_neon_vfma_laneq_v, },
@@ -7405,12 +7401,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vst4_lane_bf16, NEON::BI__builtin_neon_vst4_lane_v },
{ NEON::BI__builtin_neon_vst4q_bf16, NEON::BI__builtin_neon_vst4q_v },
{ NEON::BI__builtin_neon_vst4q_lane_bf16, NEON::BI__builtin_neon_vst4q_lane_v },
- { NEON::BI__builtin_neon_vtrn_f16, NEON::BI__builtin_neon_vtrn_v, },
- { NEON::BI__builtin_neon_vtrnq_f16, NEON::BI__builtin_neon_vtrnq_v, },
- { NEON::BI__builtin_neon_vuzp_f16, NEON::BI__builtin_neon_vuzp_v, },
- { NEON::BI__builtin_neon_vuzpq_f16, NEON::BI__builtin_neon_vuzpq_v, },
- { NEON::BI__builtin_neon_vzip_f16, NEON::BI__builtin_neon_vzip_v, },
- { NEON::BI__builtin_neon_vzipq_f16, NEON::BI__builtin_neon_vzipq_v, },
// The mangling rules cause us to have one ID for each type for vldap1(q)_lane
// and vstl1(q)_lane, but codegen is equivalent for all of them. Choose an
// arbitrary one to be handled as tha canonical variation.
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 7c66140..5443235 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -56,13 +56,7 @@ using namespace CodeGen;
// Experiment to make sanitizers easier to debug
static llvm::cl::opt<bool> ClSanitizeDebugDeoptimization(
"ubsan-unique-traps", llvm::cl::Optional,
- llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check."));
-
-// TODO: Introduce frontend options to enabled per sanitizers, similar to
-// `fsanitize-trap`.
-static llvm::cl::opt<bool> ClSanitizeExpHot(
- "ubsan-exp-hot", llvm::cl::Optional,
- llvm::cl::desc("Pass UBSAN checks if `llvm.experimental.hot()` is true."));
+ llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check"));
//===--------------------------------------------------------------------===//
// Miscellaneous Helper Methods
@@ -3804,13 +3798,6 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
SanitizerHandler CheckHandlerID) {
llvm::BasicBlock *Cont = createBasicBlock("cont");
- if (ClSanitizeExpHot) {
- llvm::Value *Allow =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::allow_ubsan_check),
- llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID));
- Checked = Builder.CreateOr(Checked, Builder.CreateNot(Allow));
- }
-
// If we're optimizing, collapse all calls to trap down to just one per
// check-type per function to save on code size.
if ((int)TrapBBs.size() <= CheckHandlerID)
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index a793b21..1facadd 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -319,12 +319,12 @@ public:
// doubles the exponent of SmallerType.LargestFiniteVal)
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
+ FPHasBeenPromoted = true;
return CGF.getContext().getComplexType(HigherElementType);
} else {
- FPHasBeenPromoted = true;
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp);
- return CGF.getContext().getComplexType(ElementType);
+ return QualType();
}
}
@@ -1037,7 +1037,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
LHSi = llvm::Constant::getNullValue(RHSi->getType());
if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
(Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted &&
- FPHasBeenPromoted))
+ !FPHasBeenPromoted))
return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index bc36331..8eb1058 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -2648,9 +2648,9 @@ void CGOpenMPRuntime::emitDistributeStaticInit(
void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPDirectiveKind DKind) {
- assert(DKind == OMPD_distribute || DKind == OMPD_for ||
- DKind == OMPD_sections &&
- "Expected distribute, for, or sections directive kind");
+ assert((DKind == OMPD_distribute || DKind == OMPD_for ||
+ DKind == OMPD_sections) &&
+ "Expected distribute, for, or sections directive kind");
if (!CGF.HaveInsertPoint())
return;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a85..c831777 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,
auto TypeInfo = getContext().getTypeInfoInChars(Ty);
+ CCState State(*const_cast<CGFunctionInfo *>(CGF.CurFnInfo));
+ ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+ // Empty records are ignored for parameter passing purposes.
+ if (AI.isIgnore())
+ return CGF.CreateMemTemp(Ty);
+
// x86-32 changes the alignment of certain arguments on the stack.
//
// Just messing with TypeInfo like this works because we never pass
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 1a0f5f2..e6c1767 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -49,6 +49,7 @@
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h"
+#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@@ -5889,6 +5890,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
&JA);
}
+ if (JA.getType() == types::TY_API_INFO &&
+ C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&
+ C.getArgs().hasArg(options::OPT_o))
+ Diag(clang::diag::err_drv_unexpected_symbol_graph_output)
+ << C.getArgs().getLastArgValue(options::OPT_o);
+
// DXC defaults to standard out when generating assembly. We check this after
// any DXC flags that might specify a file.
if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b03ac60..766a9b91 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4045,9 +4045,18 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D,
// module fragment.
CmdArgs.push_back("-fskip-odr-check-in-gmf");
- // Claim `-fmodule-output` and `-fmodule-output=` to avoid unused warnings.
- Args.ClaimAllArgs(options::OPT_fmodule_output);
- Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
+ // We need to include the case the input file is a module file here.
+ // Since the default compilation model for C++ module interface unit will
+ // create temporary module file and compile the temporary module file
+ // to get the object file. Then the `-fmodule-output` flag will be
+ // brought to the second compilation process. So we have to claim it for
+ // the case too.
+ if (Input.getType() == driver::types::TY_CXXModule ||
+ Input.getType() == driver::types::TY_PP_CXXModule ||
+ Input.getType() == driver::types::TY_ModuleFile) {
+ Args.ClaimAllArgs(options::OPT_fmodule_output);
+ Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
+ }
return HaveModules;
}
@@ -5037,11 +5046,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(JA.getType() == types::TY_API_INFO &&
"Extract API actions must generate a API information.");
CmdArgs.push_back("-extract-api");
+
+ if (Arg *PrettySGFArg = Args.getLastArg(options::OPT_emit_pretty_sgf))
+ PrettySGFArg->render(Args, CmdArgs);
+
+ Arg *SymbolGraphDirArg = Args.getLastArg(options::OPT_symbol_graph_dir_EQ);
+
if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
ProductNameArg->render(Args, CmdArgs);
if (Arg *ExtractAPIIgnoresFileArg =
Args.getLastArg(options::OPT_extract_api_ignores_EQ))
ExtractAPIIgnoresFileArg->render(Args, CmdArgs);
+ if (Arg *EmitExtensionSymbolGraphs =
+ Args.getLastArg(options::OPT_emit_extension_symbol_graphs)) {
+ if (!SymbolGraphDirArg)
+ D.Diag(diag::err_drv_missing_symbol_graph_dir);
+
+ EmitExtensionSymbolGraphs->render(Args, CmdArgs);
+ }
+ if (SymbolGraphDirArg)
+ SymbolGraphDirArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
@@ -5858,7 +5882,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CM = "large";
if (Triple.isAArch64(64)) {
Ok = CM == "tiny" || CM == "small" || CM == "large";
- if (CM == "large" && RelocationModel != llvm::Reloc::Static)
+ if (CM == "large" && !Triple.isOSBinFormatMachO() &&
+ RelocationModel != llvm::Reloc::Static)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-fno-pic";
} else if (Triple.isLoongArch()) {
diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp
index aa7a1e9..5a62c5d 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -13,514 +13,67 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/API.h"
-#include "clang/AST/CommentCommandTraits.h"
-#include "clang/AST/CommentLexer.h"
#include "clang/AST/RawCommentList.h"
+#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
#include <memory>
using namespace clang::extractapi;
using namespace llvm;
-namespace {
+SymbolReference::SymbolReference(const APIRecord *R)
+ : Name(R->Name), USR(R->USR), Record(R) {}
-template <typename RecordTy, typename... CtorArgsTy>
-RecordTy *addTopLevelRecord(DenseMap<StringRef, APIRecord *> &USRLookupTable,
- APISet::RecordMap<RecordTy> &RecordMap,
- StringRef USR, CtorArgsTy &&...CtorArgs) {
- auto Result = RecordMap.insert({USR, nullptr});
-
- // Create the record if it does not already exist
- if (Result.second)
- Result.first->second =
- std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
-
- auto *Record = Result.first->second.get();
- USRLookupTable.insert({USR, Record});
- return Record;
-}
-
-} // namespace
-
-NamespaceRecord *
-APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader);
-
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-GlobalVariableRecord *
-APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Fragments,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc,
- std::move(Availability), Linkage, Comment, Fragments,
- SubHeading, IsFromSystemHeader);
-}
-
-GlobalVariableTemplateRecord *APISet::addGlobalVariableTemplate(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalVariableTemplates, USR,
- Name, Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Template,
- IsFromSystemHeader);
-}
-
-GlobalFunctionRecord *APISet::addGlobalFunction(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Fragments,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc,
- std::move(Availability), Linkage, Comment, Fragments,
- SubHeading, Signature, IsFromSystemHeader);
-}
-
-GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- Template Template, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
- Name, Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Signature, Template,
- IsFromSystemHeader);
-}
-
-GlobalFunctionTemplateSpecializationRecord *
-APISet::addGlobalFunctionTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(
- USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
- Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
- Signature, IsFromSystemHeader);
-}
-
-EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- auto Record = std::make_unique<EnumConstantRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
- IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Enum->USR, Enum->Name, Enum->getKind(), Enum);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Enum->Constants.emplace_back(std::move(Record)).get();
-}
-
-EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
-}
-
-RecordFieldRecord *APISet::addRecordField(
- RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind, bool IsFromSystemHeader) {
- auto RecordField = std::make_unique<RecordFieldRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
- Kind, IsFromSystemHeader);
- RecordField->ParentInformation = APIRecord::HierarchyInformation(
- Record->USR, Record->Name, Record->getKind(), Record);
- USRBasedLookupTable.insert({USR, RecordField.get()});
- return Record->Fields.emplace_back(std::move(RecordField)).get();
-}
-
-RecordRecord *APISet::addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Records, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Kind, IsFromSystemHeader);
-}
-
-StaticFieldRecord *
-APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Context,
- AccessControl Access, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc,
- std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Context, Access,
- IsFromSystemHeader);
-}
-
-CXXFieldRecord *
-APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, AccessControl Access,
- bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availability),
- Comment, Declaration, SubHeading, Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
- return Record;
-}
-
-CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, Template Template, bool IsFromSystemHeader) {
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Access, Template, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
-
- return Record;
-}
-
-CXXClassRecord *
-APISet::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) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, CXXClasses, USR, Name, Loc, std::move(Availability),
- Comment, Declaration, SubHeading, Kind, Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-ClassTemplateRecord *APISet::addClassTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- Template Template, AccessControl Access, bool IsFromSystemHeader) {
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Template, Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader) {
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR,
- Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-ClassTemplatePartialSpecializationRecord *
-APISet::addClassTemplatePartialSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- Template Template, AccessControl Access, bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc,
- std::move(Availability), Comment, Declaration, SubHeading, Template,
- Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-GlobalVariableTemplateSpecializationRecord *
-APISet::addGlobalVariableTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable,
- GlobalVariableTemplateSpecializations, USR, Name,
- Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, IsFromSystemHeader);
-}
-
-GlobalVariableTemplatePartialSpecializationRecord *
-APISet::addGlobalVariableTemplatePartialSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(
- USRBasedLookupTable, GlobalVariableTemplatePartialSpecializations, USR,
- Name, Loc, std::move(Availability), Linkage, Comment, Declaration,
- SubHeading, Template, IsFromSystemHeader);
-}
-
-ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- Template Template, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Concepts, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Template, IsFromSystemHeader);
-}
-
-CXXMethodRecord *APISet::addCXXInstanceMethod(
- APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader) {
- CXXMethodRecord *Record =
- addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
-
- Record->ParentInformation = APIRecord::HierarchyInformation(
- CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
- CXXClassRecord);
- return Record;
-}
-
-CXXMethodRecord *APISet::addCXXStaticMethod(
- APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader) {
- CXXMethodRecord *Record =
- addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
-
- Record->ParentInformation = APIRecord::HierarchyInformation(
- CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
- CXXClassRecord);
- return Record;
-}
-
-CXXMethodTemplateRecord *APISet::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) {
- auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
- Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, Signature, Access,
- Template, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
-
- return Record;
-}
-
-CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader) {
-
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
- std::move(Availability), Comment, Declaration, SubHeading, Signature,
- Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
-
- return Record;
-}
-
-ObjCCategoryRecord *APISet::addObjCCategory(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- SymbolReference Interface, bool IsFromSystemHeader,
- bool IsFromExternalModule) {
- // Create the category record.
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Interface, IsFromSystemHeader);
-
- Record->IsFromExternalModule = IsFromExternalModule;
-
- auto It = ObjCInterfaces.find(Interface.USR);
- if (It != ObjCInterfaces.end())
- It->second->Categories.push_back(Record);
-
- return Record;
-}
-
-ObjCInterfaceRecord *
-APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- SymbolReference SuperClass, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
- std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, SuperClass,
- IsFromSystemHeader);
-}
-
-ObjCMethodRecord *APISet::addObjCMethod(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsInstanceMethod,
- bool IsFromSystemHeader) {
- std::unique_ptr<ObjCMethodRecord> Record;
- if (IsInstanceMethod)
- Record = std::make_unique<ObjCInstanceMethodRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, IsFromSystemHeader);
- else
- Record = std::make_unique<ObjCClassMethodRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, IsFromSystemHeader);
-
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Methods.emplace_back(std::move(Record)).get();
-}
-
-ObjCPropertyRecord *APISet::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) {
- std::unique_ptr<ObjCPropertyRecord> Record;
- if (IsInstanceProperty)
- Record = std::make_unique<ObjCInstancePropertyRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Attributes, GetterName, SetterName, IsOptional,
- IsFromSystemHeader);
- else
- Record = std::make_unique<ObjCClassPropertyRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Attributes, GetterName, SetterName, IsOptional,
- IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Properties.emplace_back(std::move(Record)).get();
-}
-
-ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
- auto Record = std::make_unique<ObjCInstanceVariableRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
- Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Ivars.emplace_back(std::move(Record)).get();
+APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) {
+ switch (Ctx->getKind()) {
+#define RECORD_CONTEXT(CLASS, KIND) \
+ case KIND: \
+ return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
+#include "clang/ExtractAPI/APIRecords.inc"
+ default:
+ return nullptr;
+ // llvm_unreachable("RecordContext derived class isn't propertly
+ // implemented");
+ }
}
-ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
+RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
+ if (!Record)
+ return nullptr;
+ switch (Record->getKind()) {
+#define RECORD_CONTEXT(CLASS, KIND) \
+ case KIND: \
+ return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
+#include "clang/ExtractAPI/APIRecords.inc"
+ default:
+ return nullptr;
+ // llvm_unreachable("RecordContext derived class isn't propertly
+ // implemented");
+ }
}
-MacroDefinitionRecord *
-APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
- Declaration, SubHeading, IsFromSystemHeader);
-}
+void RecordContext::addToRecordChain(APIRecord *Record) const {
+ if (!First) {
+ First = Record;
+ Last = Record;
+ return;
+ }
-TypedefRecord *
-APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- SymbolReference UnderlyingType, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, UnderlyingType, IsFromSystemHeader);
+ Last->NextInContext = Record;
+ Last = Record;
}
APIRecord *APISet::findRecordForUSR(StringRef USR) const {
if (USR.empty())
return nullptr;
- return USRBasedLookupTable.lookup(USR);
-}
-
-StringRef APISet::recordUSR(const Decl *D) {
- SmallString<128> USR;
- index::generateUSRForDecl(D, USR);
- return copyString(USR);
-}
+ auto FindIt = USRBasedLookupTable.find(USR);
+ if (FindIt != USRBasedLookupTable.end())
+ return FindIt->getSecond().get();
-StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
- const SourceManager &SM) {
- SmallString<128> USR;
- index::generateUSRForMacro(Name, SL, SM, USR);
- return copyString(USR);
+ return nullptr;
}
StringRef APISet::copyString(StringRef String) {
@@ -528,15 +81,22 @@ StringRef APISet::copyString(StringRef String) {
return {};
// No need to allocate memory and copy if the string has already been stored.
- if (StringAllocator.identifyObject(String.data()))
+ if (Allocator.identifyObject(String.data()))
return String;
- void *Ptr = StringAllocator.Allocate(String.size(), 1);
+ void *Ptr = Allocator.Allocate(String.size(), 1);
memcpy(Ptr, String.data(), String.size());
return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
}
+SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
+ StringRef Source) {
+ return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
+}
+
APIRecord::~APIRecord() {}
+RecordRecord::~RecordRecord() {}
+RecordFieldRecord::~RecordFieldRecord() {}
ObjCContainerRecord::~ObjCContainerRecord() {}
ObjCMethodRecord::~ObjCMethodRecord() {}
ObjCPropertyRecord::~ObjCPropertyRecord() {}
@@ -546,8 +106,10 @@ void GlobalFunctionRecord::anchor() {}
void GlobalVariableRecord::anchor() {}
void EnumConstantRecord::anchor() {}
void EnumRecord::anchor() {}
-void RecordFieldRecord::anchor() {}
-void RecordRecord::anchor() {}
+void StructFieldRecord::anchor() {}
+void StructRecord::anchor() {}
+void UnionFieldRecord::anchor() {}
+void UnionRecord::anchor() {}
void CXXFieldRecord::anchor() {}
void CXXClassRecord::anchor() {}
void CXXConstructorRecord::anchor() {}
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 22b98e0..0a24312 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -57,23 +57,44 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
} // namespace
-DeclarationFragments &DeclarationFragments::appendSpace() {
+DeclarationFragments &
+DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
if (!Fragments.empty()) {
Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text) {
// Merge the extra space into the last fragment if the last fragment is
// also text.
- if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
- Last.Spelling.push_back(' ');
+ if (Last.Spelling.back() != Character) { // avoid duplicates at end
+ Last.Spelling.push_back(Character);
}
} else {
- append(" ", FragmentKind::Text);
+ append("", FragmentKind::Text);
+ Fragments.back().Spelling.push_back(Character);
}
}
return *this;
}
+DeclarationFragments &DeclarationFragments::appendSpace() {
+ return appendUnduplicatedTextCharacter(' ');
+}
+
+DeclarationFragments &DeclarationFragments::appendSemicolon() {
+ return appendUnduplicatedTextCharacter(';');
+}
+
+DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
+ if (Fragments.empty())
+ return *this;
+
+ Fragment &Last = Fragments.back();
+ if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
+ Last.Spelling.pop_back();
+
+ return *this;
+}
+
StringRef DeclarationFragments::getFragmentKindString(
DeclarationFragments::FragmentKind Kind) {
switch (Kind) {
@@ -466,7 +487,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
if (!Decl->isAnonymousNamespace())
Fragments.appendSpace().append(
Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -508,7 +529,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
return Fragments
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -538,7 +559,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
Fragments.append(std::move(ArgumentFragment))
.appendSpace()
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
return Fragments;
}
@@ -698,7 +719,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Func->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
@@ -727,7 +748,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -743,7 +764,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
@@ -761,7 +782,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
@@ -776,7 +797,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -806,7 +827,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
@@ -846,7 +867,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -877,7 +898,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
Fragments.appendSpace().append("const",
DeclarationFragments::FragmentKind::Keyword);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -909,7 +930,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
@@ -997,7 +1018,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
.appendSpace()
.append(Concept->getName().str(),
DeclarationFragments::FragmentKind::Identifier)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1038,7 +1059,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1060,7 +1081,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1079,7 +1100,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1101,7 +1122,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1172,7 +1193,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
.appendSpace()
- .append(Category->getClassInterface()->getName(),
+ .append(Interface->getName(),
DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
Interface)
.append(" (", DeclarationFragments::FragmentKind::Text)
@@ -1246,7 +1267,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
Fragments.append(getFragmentsForParam(Param));
}
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
@@ -1347,7 +1368,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
.append(Property->getName(),
DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
@@ -1391,7 +1412,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
.appendSpace()
.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
// Instantiate template for FunctionDecl.
diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 275f49b..d633585 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -30,6 +30,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Index/USRGeneration.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
@@ -39,6 +40,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@@ -327,11 +329,12 @@ public:
StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
- StringRef USR =
- API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
+ SmallString<128> USR;
+ index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
+ USR);
- API.addMacroDefinition(
- Name, USR, Loc,
+ API.createRecord<extractapi::MacroDefinitionRecord>(
+ USR, Name, SymbolReference(), Loc,
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
@@ -372,40 +375,57 @@ private:
LocationFileChecker &LCF;
};
+std::unique_ptr<llvm::raw_pwrite_stream>
+createAdditionalSymbolGraphFile(CompilerInstance &CI, Twine BaseName) {
+ auto OutputDirectory = CI.getFrontendOpts().SymbolGraphOutputDir;
+
+ SmallString<256> FileName;
+ llvm::sys::path::append(FileName, OutputDirectory,
+ BaseName + ".symbols.json");
+ return CI.createOutputFile(
+ FileName, /*Binary*/ false, /*RemoveFileOnSignal*/ false,
+ /*UseTemporary*/ true, /*CreateMissingDirectories*/ true);
+}
+
} // namespace
-void ExtractAPIActionBase::ImplEndSourceFileAction() {
- if (!OS)
- return;
+void ExtractAPIActionBase::ImplEndSourceFileAction(CompilerInstance &CI) {
+ SymbolGraphSerializerOption SerializationOptions;
+ SerializationOptions.Compact = !CI.getFrontendOpts().EmitPrettySymbolGraphs;
+ SerializationOptions.EmitSymbolLabelsForTesting =
+ CI.getFrontendOpts().EmitSymbolGraphSymbolLabelsForTesting;
+
+ if (CI.getFrontendOpts().EmitExtensionSymbolGraphs) {
+ auto ConstructOutputFile = [&CI](Twine BaseName) {
+ return createAdditionalSymbolGraphFile(CI, BaseName);
+ };
+
+ SymbolGraphSerializer::serializeWithExtensionGraphs(
+ *OS, *API, IgnoresList, ConstructOutputFile, SerializationOptions);
+ } else {
+ SymbolGraphSerializer::serializeMainSymbolGraph(*OS, *API, IgnoresList,
+ SerializationOptions);
+ }
- // Setup a SymbolGraphSerializer to write out collected API information in
- // the Symbol Graph format.
- // FIXME: Make the kind of APISerializer configurable.
- SymbolGraphSerializer SGSerializer(*API, IgnoresList);
- SGSerializer.serialize(*OS);
+ // Flush the stream and close the main output stream.
OS.reset();
}
-std::unique_ptr<raw_pwrite_stream>
-ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
- std::unique_ptr<raw_pwrite_stream> OS;
- OS = CI.createDefaultOutputFile(/*Binary=*/false, InFile,
- /*Extension=*/"json",
- /*RemoveFileOnSignal=*/false);
- if (!OS)
- return nullptr;
- return OS;
-}
-
std::unique_ptr<ASTConsumer>
ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- OS = CreateOutputFile(CI, InFile);
+ auto ProductName = CI.getFrontendOpts().ProductName;
+
+ if (CI.getFrontendOpts().SymbolGraphOutputDir.empty())
+ OS = CI.createDefaultOutputFile(/*Binary*/ false, InFile,
+ /*Extension*/ "symbols.json",
+ /*RemoveFileOnSignal*/ false,
+ /*CreateMissingDirectories*/ true);
+ else
+ OS = createAdditionalSymbolGraphFile(CI, ProductName);
if (!OS)
return nullptr;
- auto ProductName = CI.getFrontendOpts().ProductName;
-
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
API = std::make_unique<APISet>(
@@ -495,7 +515,9 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
return true;
}
-void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); }
+void ExtractAPIAction::EndSourceFileAction() {
+ ImplEndSourceFileAction(getCompilerInstance());
+}
std::unique_ptr<ASTConsumer>
WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
@@ -506,11 +528,9 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
CreatedASTConsumer = true;
- OS = CreateOutputFile(CI, InFile);
- if (!OS)
- return nullptr;
-
- auto ProductName = CI.getFrontendOpts().ProductName;
+ ProductName = CI.getFrontendOpts().ProductName;
+ auto InputFilename = llvm::sys::path::filename(InFile);
+ OS = createAdditionalSymbolGraphFile(CI, InputFilename);
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
@@ -552,32 +572,6 @@ void WrappingExtractAPIAction::EndSourceFileAction() {
WrapperFrontendAction::EndSourceFileAction();
if (CreatedASTConsumer) {
- ImplEndSourceFileAction();
+ ImplEndSourceFileAction(getCompilerInstance());
}
}
-
-std::unique_ptr<raw_pwrite_stream>
-WrappingExtractAPIAction::CreateOutputFile(CompilerInstance &CI,
- StringRef InFile) {
- std::unique_ptr<raw_pwrite_stream> OS;
- std::string OutputDir = CI.getFrontendOpts().SymbolGraphOutputDir;
-
- // The symbol graphs need to be generated as a side effect of regular
- // compilation so the output should be dumped in the directory provided with
- // the command line option.
- llvm::SmallString<128> OutFilePath(OutputDir);
- auto Seperator = llvm::sys::path::get_separator();
- auto Infilename = llvm::sys::path::filename(InFile);
- OutFilePath.append({Seperator, Infilename});
- llvm::sys::path::replace_extension(OutFilePath, "json");
- // StringRef outputFilePathref = *OutFilePath;
-
- // don't use the default output file
- OS = CI.createOutputFile(/*OutputPath=*/OutFilePath, /*Binary=*/false,
- /*RemoveFileOnSignal=*/true,
- /*UseTemporary=*/true,
- /*CreateMissingDirectories=*/true);
- if (!OS)
- return nullptr;
- return OS;
-}
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 545860a..57f966c 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -14,13 +14,17 @@
#include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Version.h"
+#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iterator>
#include <optional>
#include <type_traits>
@@ -33,26 +37,27 @@ namespace {
/// Helper function to inject a JSON object \p Obj into another object \p Paren
/// at position \p Key.
-void serializeObject(Object &Paren, StringRef Key, std::optional<Object> Obj) {
+void serializeObject(Object &Paren, StringRef Key,
+ std::optional<Object> &&Obj) {
if (Obj)
Paren[Key] = std::move(*Obj);
}
-/// Helper function to inject a StringRef \p String into an object \p Paren at
-/// position \p Key
-void serializeString(Object &Paren, StringRef Key,
- std::optional<std::string> String) {
- if (String)
- Paren[Key] = std::move(*String);
-}
-
/// Helper function to inject a JSON array \p Array into object \p Paren at
/// position \p Key.
-void serializeArray(Object &Paren, StringRef Key, std::optional<Array> Array) {
+void serializeArray(Object &Paren, StringRef Key,
+ std::optional<Array> &&Array) {
if (Array)
Paren[Key] = std::move(*Array);
}
+/// Helper function to inject a JSON array composed of the values in \p C into
+/// object \p Paren at position \p Key.
+template <typename ContainerTy>
+void serializeArray(Object &Paren, StringRef Key, ContainerTy &&C) {
+ Paren[Key] = Array(C);
+}
+
/// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version
/// format.
///
@@ -248,6 +253,7 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
return std::nullopt;
Object DocComment;
+
Array LinesArray;
for (const auto &CommentLine : Comment) {
Object Line;
@@ -256,7 +262,8 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
serializeSourceRange(CommentLine.Begin, CommentLine.End));
LinesArray.emplace_back(std::move(Line));
}
- serializeArray(DocComment, "lines", LinesArray);
+
+ serializeArray(DocComment, "lines", std::move(LinesArray));
return DocComment;
}
@@ -322,19 +329,14 @@ serializeDeclarationFragments(const DeclarationFragments &DF) {
/// - \c subHeading : An array of declaration fragments that provides tags,
/// and potentially more tokens (for example the \c +/- symbol for
/// Objective-C methods). Can be used as sub-headings for documentation.
-Object serializeNames(const APIRecord &Record) {
+Object serializeNames(const APIRecord *Record) {
Object Names;
- if (auto *CategoryRecord =
- dyn_cast_or_null<const ObjCCategoryRecord>(&Record))
- Names["title"] =
- (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str();
- else
- Names["title"] = Record.Name;
+ Names["title"] = Record->Name;
serializeArray(Names, "subHeading",
- serializeDeclarationFragments(Record.SubHeading));
+ serializeDeclarationFragments(Record->SubHeading));
DeclarationFragments NavigatorFragments;
- NavigatorFragments.append(Record.Name,
+ NavigatorFragments.append(Record->Name,
DeclarationFragments::FragmentKind::Identifier,
/*PreciseIdentifier*/ "");
serializeArray(Names, "navigator",
@@ -351,7 +353,8 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Object Kind;
switch (RK) {
case APIRecord::RK_Unknown:
- llvm_unreachable("Records should have an explicit kind");
+ Kind["identifier"] = AddLangPrefix("unknown");
+ Kind["displayName"] = "Unknown";
break;
case APIRecord::RK_Namespace:
Kind["identifier"] = AddLangPrefix("namespace");
@@ -484,10 +487,6 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Kind["identifier"] = AddLangPrefix("class.extension");
Kind["displayName"] = "Class Extension";
break;
- case APIRecord::RK_ObjCCategoryModule:
- Kind["identifier"] = AddLangPrefix("module.extension");
- Kind["displayName"] = "Module Extension";
- break;
case APIRecord::RK_ObjCProtocol:
Kind["identifier"] = AddLangPrefix("protocol");
Kind["displayName"] = "Protocol";
@@ -500,6 +499,8 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Kind["identifier"] = AddLangPrefix("typealias");
Kind["displayName"] = "Type Alias";
break;
+ default:
+ llvm_unreachable("API Record with uninstantiable kind");
}
return Kind;
@@ -514,12 +515,18 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
return serializeSymbolKind(Record.getKind(), Lang);
}
+/// Serialize the function signature field, as specified by the
+/// Symbol Graph format.
+///
+/// The Symbol Graph function signature property contains two arrays.
+/// - The \c returns array is the declaration fragments of the return type;
+/// - The \c parameters array contains names and declaration fragments of the
+/// parameters.
template <typename RecordTy>
-std::optional<Object>
-serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) {
+void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
const auto &FS = Record.Signature;
if (FS.empty())
- return std::nullopt;
+ return;
Object Signature;
serializeArray(Signature, "returns",
@@ -537,63 +544,14 @@ serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) {
if (!Parameters.empty())
Signature["parameters"] = std::move(Parameters);
- return Signature;
+ serializeObject(Paren, "functionSignature", std::move(Signature));
}
template <typename RecordTy>
-std::optional<Object>
-serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::false_type) {
- return std::nullopt;
-}
-
-/// Serialize the function signature field, as specified by the
-/// Symbol Graph format.
-///
-/// The Symbol Graph function signature property contains two arrays.
-/// - The \c returns array is the declaration fragments of the return type;
-/// - The \c parameters array contains names and declaration fragments of the
-/// parameters.
-///
-/// \returns \c std::nullopt if \p FS is empty, or an \c Object containing the
-/// formatted function signature.
-template <typename RecordTy>
-void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
- serializeObject(Paren, "functionSignature",
- serializeFunctionSignatureMixinImpl(
- Record, has_function_signature<RecordTy>()));
-}
-
-template <typename RecordTy>
-std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
- std::true_type) {
- const auto &AccessControl = Record.Access;
- std::string Access;
- if (AccessControl.empty())
- return std::nullopt;
- Access = AccessControl.getAccess();
- return Access;
-}
-
-template <typename RecordTy>
-std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
- std::false_type) {
- return std::nullopt;
-}
-
-template <typename RecordTy>
-void serializeAccessMixin(Object &Paren, const RecordTy &Record) {
- auto accessLevel = serializeAccessMixinImpl(Record, has_access<RecordTy>());
- if (!accessLevel.has_value())
- accessLevel = "public";
- serializeString(Paren, "accessLevel", accessLevel);
-}
-
-template <typename RecordTy>
-std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
- std::true_type) {
+void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
const auto &Template = Record.Templ;
if (Template.empty())
- return std::nullopt;
+ return;
Object Generics;
Array GenericParameters;
@@ -619,97 +577,66 @@ std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
if (!GenericConstraints.empty())
Generics["constraints"] = std::move(GenericConstraints);
- return Generics;
-}
-
-template <typename RecordTy>
-std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
- std::false_type) {
- return std::nullopt;
+ serializeObject(Paren, "swiftGenerics", Generics);
}
-template <typename RecordTy>
-void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
- serializeObject(Paren, "swiftGenerics",
- serializeTemplateMixinImpl(Record, has_template<RecordTy>()));
-}
+Array generateParentContexts(const SmallVectorImpl<SymbolReference> &Parents,
+ Language Lang) {
+ Array ParentContexts;
-struct PathComponent {
- StringRef USR;
- StringRef Name;
- APIRecord::RecordKind Kind;
+ for (const auto &Parent : Parents) {
+ Object Elem;
+ Elem["usr"] = Parent.USR;
+ Elem["name"] = Parent.Name;
+ if (Parent.Record)
+ Elem["kind"] =
+ serializeSymbolKind(Parent.Record->getKind(), Lang)["identifier"];
+ else
+ Elem["kind"] =
+ serializeSymbolKind(APIRecord::RK_Unknown, Lang)["identifier"];
+ ParentContexts.emplace_back(std::move(Elem));
+ }
- PathComponent(StringRef USR, StringRef Name, APIRecord::RecordKind Kind)
- : USR(USR), Name(Name), Kind(Kind) {}
-};
+ return ParentContexts;
+}
-template <typename RecordTy>
-bool generatePathComponents(
- const RecordTy &Record, const APISet &API,
- function_ref<void(const PathComponent &)> ComponentTransformer) {
- SmallVector<PathComponent, 4> ReverseComponenents;
- ReverseComponenents.emplace_back(Record.USR, Record.Name, Record.getKind());
- const auto *CurrentParent = &Record.ParentInformation;
- bool FailedToFindParent = false;
- while (CurrentParent && !CurrentParent->empty()) {
- PathComponent CurrentParentComponent(CurrentParent->ParentUSR,
- CurrentParent->ParentName,
- CurrentParent->ParentKind);
-
- auto *ParentRecord = CurrentParent->ParentRecord;
- // Slow path if we don't have a direct reference to the ParentRecord
- if (!ParentRecord)
- ParentRecord = API.findRecordForUSR(CurrentParent->ParentUSR);
-
- // If the parent is a category extended from internal module then we need to
- // pretend this belongs to the associated interface.
- if (auto *CategoryRecord =
- dyn_cast_or_null<ObjCCategoryRecord>(ParentRecord)) {
- if (!CategoryRecord->IsFromExternalModule) {
- ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR);
- CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR,
- CategoryRecord->Interface.Name,
- APIRecord::RK_ObjCInterface);
- }
- }
-
- // The parent record doesn't exist which means the symbol shouldn't be
- // treated as part of the current product.
- if (!ParentRecord) {
- FailedToFindParent = true;
- break;
- }
-
- ReverseComponenents.push_back(std::move(CurrentParentComponent));
- CurrentParent = &ParentRecord->ParentInformation;
+/// Walk the records parent information in reverse to generate a hierarchy
+/// suitable for serialization.
+SmallVector<SymbolReference, 8>
+generateHierarchyFromRecord(const APIRecord *Record) {
+ SmallVector<SymbolReference, 8> ReverseHierarchy;
+ for (const auto *Current = Record; Current != nullptr;
+ Current = Current->Parent.Record)
+ ReverseHierarchy.emplace_back(Current);
+
+ return SmallVector<SymbolReference, 8>(
+ std::make_move_iterator(ReverseHierarchy.rbegin()),
+ std::make_move_iterator(ReverseHierarchy.rend()));
+}
+
+SymbolReference getHierarchyReference(const APIRecord *Record,
+ const APISet &API) {
+ // If the parent is a category extended from internal module then we need to
+ // pretend this belongs to the associated interface.
+ if (auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(Record)) {
+ return CategoryRecord->Interface;
+ // FIXME: TODO generate path components correctly for categories extending
+ // an external module.
}
- for (const auto &PC : reverse(ReverseComponenents))
- ComponentTransformer(PC);
-
- return FailedToFindParent;
+ return SymbolReference(Record);
}
-Object serializeParentContext(const PathComponent &PC, Language Lang) {
- Object ParentContextElem;
- ParentContextElem["usr"] = PC.USR;
- ParentContextElem["name"] = PC.Name;
- ParentContextElem["kind"] = serializeSymbolKind(PC.Kind, Lang)["identifier"];
- return ParentContextElem;
-}
+} // namespace
-template <typename RecordTy>
-Array generateParentContexts(const RecordTy &Record, const APISet &API,
- Language Lang) {
- Array ParentContexts;
- generatePathComponents(
- Record, API, [Lang, &ParentContexts](const PathComponent &PC) {
- ParentContexts.push_back(serializeParentContext(PC, Lang));
- });
+Object *ExtendedModule::addSymbol(Object &&Symbol) {
+ Symbols.emplace_back(std::move(Symbol));
+ return Symbols.back().getAsObject();
+}
- return ParentContexts;
+void ExtendedModule::addRelationship(Object &&Relationship) {
+ Relationships.emplace_back(std::move(Relationship));
}
-} // namespace
/// Defines the format version emitted by SymbolGraphSerializer.
const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
@@ -722,84 +649,44 @@ Object SymbolGraphSerializer::serializeMetadata() const {
return Metadata;
}
-Object SymbolGraphSerializer::serializeModule() const {
+Object
+SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName) const {
Object Module;
- // The user is expected to always pass `--product-name=` on the command line
- // to populate this field.
- Module["name"] = API.ProductName;
+ Module["name"] = ModuleName;
serializeObject(Module, "platform", serializePlatform(API.getTarget()));
return Module;
}
-bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
- // Skip explicitly ignored symbols.
- if (IgnoresList.shouldIgnore(Record.Name))
+bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
+ if (!Record)
return true;
// Skip unconditionally unavailable symbols
- if (Record.Availability.isUnconditionallyUnavailable())
+ if (Record->Availability.isUnconditionallyUnavailable())
return true;
// Filter out symbols prefixed with an underscored as they are understood to
// be symbols clients should not use.
- if (Record.Name.starts_with("_"))
+ if (Record->Name.starts_with("_"))
+ return true;
+
+ // Skip explicitly ignored symbols.
+ if (IgnoresList.shouldIgnore(Record->Name))
return true;
return false;
}
-template <typename RecordTy>
-std::optional<Object>
-SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
- if (shouldSkip(Record))
- return std::nullopt;
-
- Object Obj;
- serializeObject(Obj, "identifier",
- serializeIdentifier(Record, API.getLanguage()));
- serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLanguage()));
- serializeObject(Obj, "names", serializeNames(Record));
- serializeObject(
- Obj, "location",
- serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true));
- serializeArray(Obj, "availability",
- serializeAvailability(Record.Availability));
- serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
- serializeArray(Obj, "declarationFragments",
- serializeDeclarationFragments(Record.Declaration));
- SmallVector<StringRef, 4> PathComponentsNames;
- // If this returns true it indicates that we couldn't find a symbol in the
- // hierarchy.
- if (generatePathComponents(Record, API,
- [&PathComponentsNames](const PathComponent &PC) {
- PathComponentsNames.push_back(PC.Name);
- }))
- return {};
-
- serializeArray(Obj, "pathComponents", Array(PathComponentsNames));
+ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
+ if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
+ return *ModuleForCurrentSymbol;
- serializeFunctionSignatureMixin(Obj, Record);
- serializeAccessMixin(Obj, Record);
- serializeTemplateMixin(Obj, Record);
-
- return Obj;
+ return MainModule;
}
-template <typename MemberTy>
-void SymbolGraphSerializer::serializeMembers(
- const APIRecord &Record,
- const SmallVector<std::unique_ptr<MemberTy>> &Members) {
- // Members should not be serialized if we aren't recursing.
- if (!ShouldRecurse)
- return;
- for (const auto &Member : Members) {
- auto MemberRecord = serializeAPIRecord(*Member);
- if (!MemberRecord)
- continue;
-
- Symbols.emplace_back(std::move(*MemberRecord));
- serializeRelationship(RelationshipKind::MemberOf, *Member, Record);
- }
+Array SymbolGraphSerializer::serializePathComponents(
+ const APIRecord *Record) const {
+ return Array(map_range(Hierarchy, [](auto Elt) { return Elt.Name; }));
}
StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
@@ -816,6 +703,33 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
llvm_unreachable("Unhandled relationship kind");
}
+void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
+ const SymbolReference &Source,
+ const SymbolReference &Target,
+ ExtendedModule &Into) {
+ Object Relationship;
+ SmallString<64> TestRelLabel;
+ if (EmitSymbolLabelsForTesting) {
+ llvm::raw_svector_ostream OS(TestRelLabel);
+ OS << SymbolGraphSerializer::getRelationshipString(Kind) << " $ "
+ << Source.USR << " $ ";
+ if (Target.USR.empty())
+ OS << Target.Name;
+ else
+ OS << Target.USR;
+ Relationship["!testRelLabel"] = TestRelLabel;
+ }
+ Relationship["source"] = Source.USR;
+ Relationship["target"] = Target.USR;
+ Relationship["targetFallback"] = Target.Name;
+ Relationship["kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
+
+ if (ForceEmitToMainModule)
+ MainModule.addRelationship(std::move(Relationship));
+ else
+ Into.addRelationship(std::move(Relationship));
+}
+
StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
switch (Kind) {
case ConstraintKind::Conformance:
@@ -826,430 +740,324 @@ StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
llvm_unreachable("Unhandled constraint kind");
}
-void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
- SymbolReference Source,
- SymbolReference Target) {
- Object Relationship;
- Relationship["source"] = Source.USR;
- Relationship["target"] = Target.USR;
- Relationship["targetFallback"] = Target.Name;
- Relationship["kind"] = getRelationshipString(Kind);
-
- Relationships.emplace_back(std::move(Relationship));
-}
+void SymbolGraphSerializer::serializeAPIRecord(const APIRecord *Record) {
+ Object Obj;
-void SymbolGraphSerializer::visitNamespaceRecord(
- const NamespaceRecord &Record) {
- auto Namespace = serializeAPIRecord(Record);
- if (!Namespace)
- return;
- Symbols.emplace_back(std::move(*Namespace));
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
-}
+ // If we need symbol labels for testing emit the USR as the value and the key
+ // starts with '!'' to ensure it ends up at the top of the object.
+ if (EmitSymbolLabelsForTesting)
+ Obj["!testLabel"] = Record->USR;
-void SymbolGraphSerializer::visitGlobalFunctionRecord(
- const GlobalFunctionRecord &Record) {
- auto Obj = serializeAPIRecord(Record);
- if (!Obj)
- return;
+ serializeObject(Obj, "identifier",
+ serializeIdentifier(*Record, API.getLanguage()));
+ serializeObject(Obj, "kind", serializeSymbolKind(*Record, API.getLanguage()));
+ serializeObject(Obj, "names", serializeNames(Record));
+ serializeObject(
+ Obj, "location",
+ serializeSourceLocation(Record->Location, /*IncludeFileURI=*/true));
+ serializeArray(Obj, "availability",
+ serializeAvailability(Record->Availability));
+ serializeObject(Obj, "docComment", serializeDocComment(Record->Comment));
+ serializeArray(Obj, "declarationFragments",
+ serializeDeclarationFragments(Record->Declaration));
- Symbols.emplace_back(std::move(*Obj));
-}
+ Obj["pathComponents"] = serializePathComponents(Record);
+ Obj["accessLevel"] = Record->Access.getAccess();
-void SymbolGraphSerializer::visitGlobalVariableRecord(
- const GlobalVariableRecord &Record) {
- auto Obj = serializeAPIRecord(Record);
- if (!Obj)
- return;
+ ExtendedModule &Module = getModuleForCurrentSymbol();
+ // If the hierarchy has at least one parent and child.
+ if (Hierarchy.size() >= 2)
+ serializeRelationship(MemberOf, Hierarchy.back(),
+ Hierarchy[Hierarchy.size() - 2], Module);
- Symbols.emplace_back(std::move(*Obj));
+ CurrentSymbol = Module.addSymbol(std::move(Obj));
}
-void SymbolGraphSerializer::visitEnumRecord(const EnumRecord &Record) {
- auto Enum = serializeAPIRecord(Record);
- if (!Enum)
- return;
-
- Symbols.emplace_back(std::move(*Enum));
- serializeMembers(Record, Record.Constants);
+bool SymbolGraphSerializer::traverseAPIRecord(const APIRecord *Record) {
+ if (!Record)
+ return true;
+ if (shouldSkip(Record))
+ return true;
+ Hierarchy.push_back(getHierarchyReference(Record, API));
+ // Defer traversal mechanics to APISetVisitor base implementation
+ auto RetVal = Base::traverseAPIRecord(Record);
+ Hierarchy.pop_back();
+ return RetVal;
}
-void SymbolGraphSerializer::visitRecordRecord(const RecordRecord &Record) {
- auto SerializedRecord = serializeAPIRecord(Record);
- if (!SerializedRecord)
- return;
-
- Symbols.emplace_back(std::move(*SerializedRecord));
- serializeMembers(Record, Record.Fields);
+bool SymbolGraphSerializer::visitAPIRecord(const APIRecord *Record) {
+ serializeAPIRecord(Record);
+ return true;
}
-void SymbolGraphSerializer::visitStaticFieldRecord(
- const StaticFieldRecord &Record) {
- auto StaticField = serializeAPIRecord(Record);
- if (!StaticField)
- return;
- Symbols.emplace_back(std::move(*StaticField));
- serializeRelationship(RelationshipKind::MemberOf, Record, Record.Context);
+bool SymbolGraphSerializer::visitGlobalFunctionRecord(
+ const GlobalFunctionRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
+
+ serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
+bool SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*Class));
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ for (const auto &Base : Record->Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base,
+ getModuleForCurrentSymbol());
+ return true;
}
-void SymbolGraphSerializer::visitClassTemplateRecord(
- const ClassTemplateRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
+bool SymbolGraphSerializer::visitClassTemplateRecord(
+ const ClassTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*Class));
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitClassTemplateSpecializationRecord(
- const ClassTemplateSpecializationRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
-
- Symbols.emplace_back(std::move(*Class));
+bool SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
-
- Symbols.emplace_back(std::move(*Class));
+bool SymbolGraphSerializer::visitCXXMethodRecord(
+ const CXXMethodRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXInstanceMethodRecord(
- const CXXInstanceMethodRecord &Record) {
- auto InstanceMethod = serializeAPIRecord(Record);
- if (!InstanceMethod)
- return;
+bool SymbolGraphSerializer::visitCXXMethodTemplateRecord(
+ const CXXMethodTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*InstanceMethod));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXStaticMethodRecord(
- const CXXStaticMethodRecord &Record) {
- auto StaticMethod = serializeAPIRecord(Record);
- if (!StaticMethod)
- return;
+bool SymbolGraphSerializer::visitCXXFieldTemplateRecord(
+ const CXXFieldTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*StaticMethod));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitMethodTemplateRecord(
- const CXXMethodTemplateRecord &Record) {
- if (!ShouldRecurse)
- // Ignore child symbols
- return;
- auto MethodTemplate = serializeAPIRecord(Record);
- if (!MethodTemplate)
- return;
- Symbols.emplace_back(std::move(*MethodTemplate));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
-}
+bool SymbolGraphSerializer::visitConceptRecord(const ConceptRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord(
- const CXXMethodTemplateSpecializationRecord &Record) {
- if (!ShouldRecurse)
- // Ignore child symbols
- return;
- auto MethodTemplateSpecialization = serializeAPIRecord(Record);
- if (!MethodTemplateSpecialization)
- return;
- Symbols.emplace_back(std::move(*MethodTemplateSpecialization));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXFieldRecord(const CXXFieldRecord &Record) {
- if (!ShouldRecurse)
- return;
- auto CXXField = serializeAPIRecord(Record);
- if (!CXXField)
- return;
- Symbols.emplace_back(std::move(*CXXField));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
-}
+bool SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
+ const GlobalVariableTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitCXXFieldTemplateRecord(
- const CXXFieldTemplateRecord &Record) {
- if (!ShouldRecurse)
- // Ignore child symbols
- return;
- auto CXXFieldTemplate = serializeAPIRecord(Record);
- if (!CXXFieldTemplate)
- return;
- Symbols.emplace_back(std::move(*CXXFieldTemplate));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) {
- auto Concept = serializeAPIRecord(Record);
- if (!Concept)
- return;
+bool SymbolGraphSerializer::
+ visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*Concept));
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
- const GlobalVariableTemplateRecord &Record) {
- auto GlobalVariableTemplate = serializeAPIRecord(Record);
- if (!GlobalVariableTemplate)
- return;
- Symbols.emplace_back(std::move(*GlobalVariableTemplate));
-}
+bool SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
+ const GlobalFunctionTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitGlobalVariableTemplateSpecializationRecord(
- const GlobalVariableTemplateSpecializationRecord &Record) {
- auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record);
- if (!GlobalVariableTemplateSpecialization)
- return;
- Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization));
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::
- visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord &Record) {
- auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record);
- if (!GlobalVariableTemplatePartialSpecialization)
- return;
- Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization));
-}
+bool SymbolGraphSerializer::visitObjCContainerRecord(
+ const ObjCContainerRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
- const GlobalFunctionTemplateRecord &Record) {
- auto GlobalFunctionTemplate = serializeAPIRecord(Record);
- if (!GlobalFunctionTemplate)
- return;
- Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
-}
+ for (const auto &Protocol : Record->Protocols)
+ serializeRelationship(ConformsTo, Record, Protocol,
+ getModuleForCurrentSymbol());
-void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord(
- const GlobalFunctionTemplateSpecializationRecord &Record) {
- auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record);
- if (!GlobalFunctionTemplateSpecialization)
- return;
- Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization));
+ return true;
}
-void SymbolGraphSerializer::visitObjCContainerRecord(
- const ObjCContainerRecord &Record) {
- auto ObjCContainer = serializeAPIRecord(Record);
- if (!ObjCContainer)
- return;
+bool SymbolGraphSerializer::visitObjCInterfaceRecord(
+ const ObjCInterfaceRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*ObjCContainer));
-
- serializeMembers(Record, Record.Ivars);
- serializeMembers(Record, Record.Methods);
- serializeMembers(Record, Record.Properties);
-
- for (const auto &Protocol : Record.Protocols)
- // Record that Record conforms to Protocol.
- serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
-
- if (auto *ObjCInterface = dyn_cast<ObjCInterfaceRecord>(&Record)) {
- if (!ObjCInterface->SuperClass.empty())
- // If Record is an Objective-C interface record and it has a super class,
- // record that Record is inherited from SuperClass.
- serializeRelationship(RelationshipKind::InheritsFrom, Record,
- ObjCInterface->SuperClass);
-
- // Members of categories extending an interface are serialized as members of
- // the interface.
- for (const auto *Category : ObjCInterface->Categories) {
- serializeMembers(Record, Category->Ivars);
- serializeMembers(Record, Category->Methods);
- serializeMembers(Record, Category->Properties);
-
- // Surface the protocols of the category to the interface.
- for (const auto &Protocol : Category->Protocols)
- serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
- }
- }
+ if (!Record->SuperClass.empty())
+ serializeRelationship(InheritsFrom, Record, Record->SuperClass,
+ getModuleForCurrentSymbol());
+ return true;
}
-void SymbolGraphSerializer::visitObjCCategoryRecord(
- const ObjCCategoryRecord &Record) {
- if (!Record.IsFromExternalModule)
- return;
-
- // Check if the current Category' parent has been visited before, if so skip.
- if (!visitedCategories.contains(Record.Interface.Name)) {
- visitedCategories.insert(Record.Interface.Name);
- Object Obj;
- serializeObject(Obj, "identifier",
- serializeIdentifier(Record, API.getLanguage()));
- serializeObject(Obj, "kind",
- serializeSymbolKind(APIRecord::RK_ObjCCategoryModule,
- API.getLanguage()));
- Obj["accessLevel"] = "public";
- Symbols.emplace_back(std::move(Obj));
- }
+bool SymbolGraphSerializer::traverseObjCCategoryRecord(
+ const ObjCCategoryRecord *Record) {
+ auto *CurrentModule = ModuleForCurrentSymbol;
+ if (Record->isExtendingExternalModule())
+ ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source];
- Object Relationship;
- Relationship["source"] = Record.USR;
- Relationship["target"] = Record.Interface.USR;
- Relationship["targetFallback"] = Record.Interface.Name;
- Relationship["kind"] = getRelationshipString(RelationshipKind::ExtensionTo);
- Relationships.emplace_back(std::move(Relationship));
+ if (!walkUpFromObjCCategoryRecord(Record))
+ return false;
- auto ObjCCategory = serializeAPIRecord(Record);
+ bool RetVal = traverseRecordContext(Record);
+ ModuleForCurrentSymbol = CurrentModule;
+ return RetVal;
+}
- if (!ObjCCategory)
- return;
+bool SymbolGraphSerializer::walkUpFromObjCCategoryRecord(
+ const ObjCCategoryRecord *Record) {
+ return visitObjCCategoryRecord(Record);
+}
- Symbols.emplace_back(std::move(*ObjCCategory));
- serializeMembers(Record, Record.Methods);
- serializeMembers(Record, Record.Properties);
+bool SymbolGraphSerializer::visitObjCCategoryRecord(
+ const ObjCCategoryRecord *Record) {
+ // If we need to create a record for the category in the future do so here,
+ // otherwise everything is set up to pretend that the category is in fact the
+ // interface it extends.
+ for (const auto &Protocol : Record->Protocols)
+ serializeRelationship(ConformsTo, Record->Interface, Protocol,
+ getModuleForCurrentSymbol());
- // Surface the protocols of the category to the interface.
- for (const auto &Protocol : Record.Protocols)
- serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
+ return true;
}
-void SymbolGraphSerializer::visitMacroDefinitionRecord(
- const MacroDefinitionRecord &Record) {
- auto Macro = serializeAPIRecord(Record);
+bool SymbolGraphSerializer::visitObjCMethodRecord(
+ const ObjCMethodRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- if (!Macro)
- return;
+ serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
+ return true;
+}
- Symbols.emplace_back(std::move(*Macro));
+bool SymbolGraphSerializer::visitObjCInstanceVariableRecord(
+ const ObjCInstanceVariableRecord *Record) {
+ // FIXME: serialize ivar access control here.
+ return true;
}
-void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
- switch (Record->getKind()) {
- case APIRecord::RK_Unknown:
- llvm_unreachable("Records should have a known kind!");
- case APIRecord::RK_GlobalFunction:
- visitGlobalFunctionRecord(*cast<GlobalFunctionRecord>(Record));
- break;
- case APIRecord::RK_GlobalVariable:
- visitGlobalVariableRecord(*cast<GlobalVariableRecord>(Record));
- break;
- case APIRecord::RK_Enum:
- visitEnumRecord(*cast<EnumRecord>(Record));
- break;
- case APIRecord::RK_Struct:
- LLVM_FALLTHROUGH;
- case APIRecord::RK_Union:
- visitRecordRecord(*cast<RecordRecord>(Record));
- break;
- case APIRecord::RK_StaticField:
- visitStaticFieldRecord(*cast<StaticFieldRecord>(Record));
- break;
- case APIRecord::RK_CXXClass:
- visitCXXClassRecord(*cast<CXXClassRecord>(Record));
- break;
- case APIRecord::RK_ObjCInterface:
- visitObjCContainerRecord(*cast<ObjCInterfaceRecord>(Record));
- break;
- case APIRecord::RK_ObjCProtocol:
- visitObjCContainerRecord(*cast<ObjCProtocolRecord>(Record));
- break;
- case APIRecord::RK_ObjCCategory:
- visitObjCCategoryRecord(*cast<ObjCCategoryRecord>(Record));
- break;
- case APIRecord::RK_MacroDefinition:
- visitMacroDefinitionRecord(*cast<MacroDefinitionRecord>(Record));
- break;
- case APIRecord::RK_Typedef:
- visitTypedefRecord(*cast<TypedefRecord>(Record));
- break;
- default:
- if (auto Obj = serializeAPIRecord(*Record)) {
- Symbols.emplace_back(std::move(*Obj));
- auto &ParentInformation = Record->ParentInformation;
- if (!ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, *Record,
- *ParentInformation.ParentRecord);
- }
- break;
- }
+bool SymbolGraphSerializer::walkUpFromTypedefRecord(
+ const TypedefRecord *Record) {
+ // Short-circuit walking up the class hierarchy and handle creating typedef
+ // symbol objects manually as there are additional symbol dropping rules to
+ // respect.
+ return visitTypedefRecord(Record);
}
-void SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord &Record) {
+bool SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord *Record) {
// Typedefs of anonymous types have their entries unified with the underlying
// type.
- bool ShouldDrop = Record.UnderlyingType.Name.empty();
+ bool ShouldDrop = Record->UnderlyingType.Name.empty();
// enums declared with `NS_OPTION` have a named enum and a named typedef, with
// the same name
- ShouldDrop |= (Record.UnderlyingType.Name == Record.Name);
+ ShouldDrop |= (Record->UnderlyingType.Name == Record->Name);
if (ShouldDrop)
- return;
+ return true;
- auto Typedef = serializeAPIRecord(Record);
- if (!Typedef)
- return;
+ // Create the symbol record if the other symbol droppping rules permit it.
+ serializeAPIRecord(Record);
+ if (!CurrentSymbol)
+ return true;
- (*Typedef)["type"] = Record.UnderlyingType.USR;
+ (*CurrentSymbol)["type"] = Record->UnderlyingType.USR;
- Symbols.emplace_back(std::move(*Typedef));
+ return true;
}
-Object SymbolGraphSerializer::serialize() {
- traverseAPISet();
- return serializeCurrentGraph();
+void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
+ switch (Record->getKind()) {
+ // dispatch to the relevant walkUpFromMethod
+#define CONCRETE_RECORD(CLASS, BASE, KIND) \
+ case APIRecord::KIND: { \
+ walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
+ break; \
+ }
+#include "clang/ExtractAPI/APIRecords.inc"
+ // otherwise fallback on the only behavior we can implement safely.
+ case APIRecord::RK_Unknown:
+ visitAPIRecord(Record);
+ break;
+ default:
+ llvm_unreachable("API Record with uninstantiable kind");
+ }
}
-Object SymbolGraphSerializer::serializeCurrentGraph() {
+Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
+ ExtendedModule &&EM) {
Object Root;
serializeObject(Root, "metadata", serializeMetadata());
- serializeObject(Root, "module", serializeModule());
+ serializeObject(Root, "module", serializeModuleObject(ModuleName));
- Root["symbols"] = std::move(Symbols);
- Root["relationships"] = std::move(Relationships);
+ Root["symbols"] = std::move(EM.Symbols);
+ Root["relationships"] = std::move(EM.Relationships);
return Root;
}
-void SymbolGraphSerializer::serialize(raw_ostream &os) {
- Object root = serialize();
+void SymbolGraphSerializer::serializeGraphToStream(
+ raw_ostream &OS, SymbolGraphSerializerOption Options, StringRef ModuleName,
+ ExtendedModule &&EM) {
+ Object Root = serializeGraph(ModuleName, std::move(EM));
if (Options.Compact)
- os << formatv("{0}", Value(std::move(root))) << "\n";
+ OS << formatv("{0}", Value(std::move(Root))) << "\n";
else
- os << formatv("{0:2}", Value(std::move(root))) << "\n";
+ OS << formatv("{0:2}", Value(std::move(Root))) << "\n";
+}
+
+void SymbolGraphSerializer::serializeMainSymbolGraph(
+ raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList,
+ SymbolGraphSerializerOption Options) {
+ SymbolGraphSerializer Serializer(API, IgnoresList,
+ Options.EmitSymbolLabelsForTesting);
+ Serializer.traverseAPISet();
+ Serializer.serializeGraphToStream(OS, Options, API.ProductName,
+ std::move(Serializer.MainModule));
+ // FIXME: TODO handle extended modules here
+}
+
+void SymbolGraphSerializer::serializeWithExtensionGraphs(
+ raw_ostream &MainOutput, const APISet &API,
+ const APIIgnoresList &IgnoresList,
+ llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
+ CreateOutputStream,
+ SymbolGraphSerializerOption Options) {
+ SymbolGraphSerializer Serializer(API, IgnoresList,
+ Options.EmitSymbolLabelsForTesting);
+ Serializer.traverseAPISet();
+
+ Serializer.serializeGraphToStream(MainOutput, Options, API.ProductName,
+ std::move(Serializer.MainModule));
+
+ for (auto &ExtensionSGF : Serializer.ExtendedModules) {
+ if (auto ExtensionOS =
+ CreateOutputStream(ExtensionSGF.getKey() + "@" + API.ProductName))
+ Serializer.serializeGraphToStream(*ExtensionOS, Options,
+ ExtensionSGF.getKey(),
+ std::move(ExtensionSGF.getValue()));
+ }
}
std::optional<Object>
@@ -1262,14 +1070,20 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object Root;
APIIgnoresList EmptyIgnores;
SymbolGraphSerializer Serializer(API, EmptyIgnores,
- /*Options.Compact*/ {true},
- /*ShouldRecurse*/ false);
+ /*EmitSymbolLabelsForTesting*/ false,
+ /*ForceEmitToMainModule*/ true);
+
+ // Set up serializer parent chain
+ Serializer.Hierarchy = generateHierarchyFromRecord(Record);
+
Serializer.serializeSingleRecord(Record);
- serializeObject(Root, "symbolGraph", Serializer.serializeCurrentGraph());
+ serializeObject(Root, "symbolGraph",
+ Serializer.serializeGraph(API.ProductName,
+ std::move(Serializer.MainModule)));
Language Lang = API.getLanguage();
serializeArray(Root, "parentContexts",
- generateParentContexts(*Record, API, Lang));
+ generateParentContexts(Serializer.Hierarchy, Lang));
Array RelatedSymbols;
@@ -1287,14 +1101,15 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object RelatedSymbol;
RelatedSymbol["usr"] = RelatedRecord->USR;
RelatedSymbol["declarationLanguage"] = getLanguageName(Lang);
- // TODO: once we record this properly let's serialize it right.
- RelatedSymbol["accessLevel"] = "public";
+ RelatedSymbol["accessLevel"] = RelatedRecord->Access.getAccess();
RelatedSymbol["filePath"] = RelatedRecord->Location.getFilename();
RelatedSymbol["moduleName"] = API.ProductName;
RelatedSymbol["isSystem"] = RelatedRecord->IsFromSystemHeader;
serializeArray(RelatedSymbol, "parentContexts",
- generateParentContexts(*RelatedRecord, API, Lang));
+ generateParentContexts(
+ generateHierarchyFromRecord(RelatedRecord), Lang));
+
RelatedSymbols.push_back(std::move(RelatedSymbol));
}
diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
index 3a5f62c..41e4e0c 100644
--- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
+++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
+#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
using namespace clang;
@@ -50,17 +51,20 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
SmallString<128> TypeUSR;
const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
const TypedefType *TypedefTy = Type->getAs<TypedefType>();
+ StringRef OwningModuleName;
if (TypeDecl) {
if (!TypedefTy)
TypeName = TypeDecl->getName().str();
clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
+ if (auto *OwningModule = TypeDecl->getImportedOwningModule())
+ OwningModuleName = OwningModule->Name;
} else {
clang::index::generateUSRForType(Type, Context, TypeUSR);
}
- return {API.copyString(TypeName), API.copyString(TypeUSR)};
+ return API.createSymbolReference(TypeName, TypeUSR, OwningModuleName);
}
std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index e41cf29..89e6c19 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3581,7 +3581,7 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
// We need to use lambda function here since there are two versions of
// `cleanup`.
auto Cleanup = [](const FormatStyle &Style, StringRef Code,
- std::vector<tooling::Range> Ranges,
+ ArrayRef<tooling::Range> Ranges,
StringRef FileName) -> tooling::Replacements {
return cleanup(Style, Code, Ranges, FileName);
};
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index a405a34..3e9988d 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -3889,6 +3889,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
}
} else if (ClosingParen) {
for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {
+ if (Tok->is(TT_CtorInitializerColon))
+ break;
if (Tok->is(tok::arrow)) {
Tok->setType(TT_TrailingReturnArrow);
break;
diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp
index 9b0ef30..fdf05c3 100644
--- a/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -290,8 +290,7 @@ private:
class PrecompilePreambleConsumer : public PCHGenerator {
public:
- PrecompilePreambleConsumer(PrecompilePreambleAction &Action,
- const Preprocessor &PP,
+ PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP,
InMemoryModuleCache &ModuleCache,
StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer)
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 2446aee..f85f036 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -181,9 +181,13 @@ CreateFrontendAction(CompilerInstance &CI) {
#endif
// Wrap the base FE action in an extract api action to generate
- // symbol graph as a biproduct of compilation ( enabled with
- // --emit-symbol-graph option )
- if (!FEOpts.SymbolGraphOutputDir.empty()) {
+ // symbol graph as a biproduct of compilation (enabled with
+ // --emit-symbol-graph option)
+ if (FEOpts.EmitSymbolGraph) {
+ if (FEOpts.SymbolGraphOutputDir.empty()) {
+ CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);
+ CI.getFrontendOpts().SymbolGraphOutputDir = ".";
+ }
CI.getCodeGenOpts().ClearASTBeforeBackend = false;
Act = std::make_unique<WrappingExtractAPIAction>(std::move(Act));
}
diff --git a/clang/lib/Headers/__stddef_unreachable.h b/clang/lib/Headers/__stddef_unreachable.h
index 518580c..61df43e 100644
--- a/clang/lib/Headers/__stddef_unreachable.h
+++ b/clang/lib/Headers/__stddef_unreachable.h
@@ -7,6 +7,8 @@
*===-----------------------------------------------------------------------===
*/
+#ifndef __cplusplus
+
/*
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
* and needs to behave as if it was textual.
@@ -15,3 +17,5 @@
(__has_feature(modules) && !__building_module(_Builtin_stddef))
#define unreachable() __builtin_unreachable()
#endif
+
+#endif
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5c11528..cbd84dd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2188,8 +2188,21 @@ void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD,
assert(iter->getSecond() >= 0 &&
"Found a negative number of references to a VarDecl");
- if (iter->getSecond() != 0)
- return;
+ if (int RefCnt = iter->getSecond(); RefCnt > 0) {
+ // Assume the given VarDecl is "used" if its ref count stored in
+ // `RefMinusAssignments` is positive, with one exception.
+ //
+ // For a C++ variable whose decl (with initializer) entirely consist the
+ // condition expression of a if/while/for construct,
+ // Clang creates a DeclRefExpr for the condition expression rather than a
+ // BinaryOperator of AssignmentOp. Thus, the C++ variable's ref
+ // count stored in `RefMinusAssignment` equals 1 when the variable is never
+ // used in the body of the if/while/for construct.
+ bool UnusedCXXCondDecl = VD->isCXXCondDecl() && (RefCnt == 1);
+ if (!UnusedCXXCondDecl)
+ return;
+ }
+
unsigned DiagID = isa<ParmVarDecl>(VD) ? diag::warn_unused_but_set_parameter
: diag::warn_unused_but_set_variable;
DiagReceiver(VD->getLocation(), PDiag(DiagID) << VD);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f32ff39..068a2e4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18564,6 +18564,9 @@ DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
return true;
}
+ if (auto *VD = dyn_cast<VarDecl>(Dcl))
+ VD->setCXXCondDecl();
+
return Dcl;
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 80b4257..6b2eb24 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2751,7 +2751,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
QualType type = VD->getType().getNonReferenceType();
// This will eventually be translated into MemberExpr upon
// the use of instantiated struct fields.
- return BuildDeclRefExpr(VD, type, VK_PRValue, NameLoc);
+ return BuildDeclRefExpr(VD, type, VK_LValue, NameLoc);
}
}
}
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 691857e..a033927 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -406,8 +406,8 @@ static void CheckForDuplicateLoopAttrs(Sema &S, ArrayRef<const Attr *> Attrs) {
<< *FirstItr;
S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
}
- return;
}
+ return;
}
static Attr *handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index a2b8cc1..d3def13 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2711,7 +2711,6 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
- TTP->getIndex();
MarkAppeared(TTP->getDecl());
return true;
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 004859e..9a39e7d 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6622,17 +6622,17 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
while (NumLocations--) {
assert(Idx < Record.size() &&
"Invalid data, missing pragma diagnostic states");
- SourceLocation Loc = ReadSourceLocation(F, Record[Idx++]);
- auto IDAndOffset = SourceMgr.getDecomposedLoc(Loc);
- assert(IDAndOffset.first.isValid() && "invalid FileID for transition");
- assert(IDAndOffset.second == 0 && "not a start location for a FileID");
+ FileID FID = ReadFileID(F, Record, Idx);
+ assert(FID.isValid() && "invalid FileID for transition");
+ // FIXME: Remove this once we don't need the side-effects.
+ (void)SourceMgr.getSLocEntryOrNull(FID);
unsigned Transitions = Record[Idx++];
// Note that we don't need to set up Parent/ParentOffset here, because
// we won't be changing the diagnostic state within imported FileIDs
// (other than perhaps appending to the main source file, which has no
// parent).
- auto &F = Diag.DiagStatesByLoc.Files[IDAndOffset.first];
+ auto &F = Diag.DiagStatesByLoc.Files[FID];
F.StateTransitions.reserve(F.StateTransitions.size() + Transitions);
for (unsigned I = 0; I != Transitions; ++I) {
unsigned Offset = Record[Idx++];
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a2668e6..ba6a8a5 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -3131,9 +3131,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
continue;
++NumLocations;
- SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0);
- assert(!Loc.isInvalid() && "start loc for valid FileID is invalid");
- AddSourceLocation(Loc, Record);
+ AddFileID(FileIDAndFile.first, Record);
Record.push_back(FileIDAndFile.second.StateTransitions.size());
for (auto &StatePoint : FileIDAndFile.second.StateTransitions) {
@@ -5109,69 +5107,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D));
- {
- auto Abv = std::make_shared<BitCodeAbbrev>();
- Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
- Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
- Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
- UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));
- }
-
- RecordData DeclUpdatesOffsetsRecord;
-
- // Keep writing types, declarations, and declaration update records
- // until we've emitted all of them.
- Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5);
- DeclTypesBlockStartOffset = Stream.GetCurrentBitNo();
- WriteTypeAbbrevs();
- WriteDeclAbbrevs();
- do {
- WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord);
- while (!DeclTypesToEmit.empty()) {
- DeclOrType DOT = DeclTypesToEmit.front();
- DeclTypesToEmit.pop();
- if (DOT.isType())
- WriteType(DOT.getType());
- else
- WriteDecl(Context, DOT.getDecl());
- }
- } while (!DeclUpdates.empty());
- Stream.ExitBlock();
-
- DoneWritingDeclsAndTypes = true;
-
- // These things can only be done once we've written out decls and types.
- WriteTypeDeclOffsets();
- if (!DeclUpdatesOffsetsRecord.empty())
- Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
-
- // Create a lexical update block containing all of the declarations in the
- // translation unit that do not come from other AST files.
- {
- SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
- for (const auto *D : TU->noload_decls()) {
- if (!D->isFromASTFile()) {
- NewGlobalKindDeclPairs.push_back(D->getKind());
- NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
- }
- }
-
- auto Abv = std::make_shared<BitCodeAbbrev>();
- Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
- Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
- unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));
-
- RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};
- Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
- bytes(NewGlobalKindDeclPairs));
- }
-
- // And a visible updates block for the translation unit.
- WriteDeclContextVisibleUpdate(TU);
-
- // If we have any extern "C" names, write out a visible update for them.
- if (Context.ExternCContext)
- WriteDeclContextVisibleUpdate(Context.ExternCContext);
+ WriteDeclAndTypes(Context);
WriteFileDeclIDsMap();
WriteSourceManagerBlock(Context.getSourceManager(), PP);
@@ -5257,10 +5193,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
if (!DeleteExprsToAnalyze.empty())
Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);
- // Write the visible updates to DeclContexts.
- for (auto *DC : UpdatedDeclContexts)
- WriteDeclContextVisibleUpdate(DC);
-
if (!WritingModule) {
// Write the submodules that were imported, if any.
struct ModuleInfo {
@@ -5325,6 +5257,72 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
return backpatchSignature();
}
+void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
+ // Keep writing types, declarations, and declaration update records
+ // until we've emitted all of them.
+ RecordData DeclUpdatesOffsetsRecord;
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5);
+ DeclTypesBlockStartOffset = Stream.GetCurrentBitNo();
+ WriteTypeAbbrevs();
+ WriteDeclAbbrevs();
+ do {
+ WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord);
+ while (!DeclTypesToEmit.empty()) {
+ DeclOrType DOT = DeclTypesToEmit.front();
+ DeclTypesToEmit.pop();
+ if (DOT.isType())
+ WriteType(DOT.getType());
+ else
+ WriteDecl(Context, DOT.getDecl());
+ }
+ } while (!DeclUpdates.empty());
+ Stream.ExitBlock();
+
+ DoneWritingDeclsAndTypes = true;
+
+ // These things can only be done once we've written out decls and types.
+ WriteTypeDeclOffsets();
+ if (!DeclUpdatesOffsetsRecord.empty())
+ Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
+
+ const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ // Create a lexical update block containing all of the declarations in the
+ // translation unit that do not come from other AST files.
+ SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
+ for (const auto *D : TU->noload_decls()) {
+ if (!D->isFromASTFile()) {
+ NewGlobalKindDeclPairs.push_back(D->getKind());
+ NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
+ }
+ }
+
+ auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
+ Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));
+
+ RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};
+ Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
+ bytes(NewGlobalKindDeclPairs));
+
+ Abv = std::make_shared<llvm::BitCodeAbbrev>();
+ Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));
+
+ // And a visible updates block for the translation unit.
+ WriteDeclContextVisibleUpdate(TU);
+
+ // If we have any extern "C" names, write out a visible update for them.
+ if (Context.ExternCContext)
+ WriteDeclContextVisibleUpdate(Context.ExternCContext);
+
+ // Write the visible updates to DeclContexts.
+ for (auto *DC : UpdatedDeclContexts)
+ WriteDeclContextVisibleUpdate(DC);
+}
+
void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
if (DeclUpdates.empty())
return;
diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp
index f54db36..2fece29 100644
--- a/clang/lib/Serialization/GeneratePCH.cpp
+++ b/clang/lib/Serialization/GeneratePCH.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Serialization/ASTReader.h"
@@ -23,8 +24,8 @@
using namespace clang;
PCHGenerator::PCHGenerator(
- const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
- StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
+ Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile,
+ StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors, bool IncludeTimestamps,
bool BuildingImplicitModule, bool ShouldCacheASTInMemory,
@@ -88,7 +89,7 @@ ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
return &Writer;
}
-ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP,
+ReducedBMIGenerator::ReducedBMIGenerator(Preprocessor &PP,
InMemoryModuleCache &ModuleCache,
StringRef OutputFile)
: PCHGenerator(
@@ -101,12 +102,24 @@ ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP,
Module *ReducedBMIGenerator::getEmittingModule(ASTContext &Ctx) {
Module *M = Ctx.getCurrentNamedModule();
- assert(M->isNamedModuleUnit() &&
+ assert(M && M->isNamedModuleUnit() &&
"ReducedBMIGenerator should only be used with C++20 Named modules.");
return M;
}
void ReducedBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) {
+ // We need to do this to make sure the size of reduced BMI not to be larger
+ // than full BMI.
+ //
+ // FIMXE: We'd better to wrap such options to a new class ASTWriterOptions
+ // since this is not about searching header really.
+ // FIXME2: We'd better to move the class writing full BMI with reduced BMI.
+ HeaderSearchOptions &HSOpts =
+ getPreprocessor().getHeaderSearchInfo().getHeaderSearchOpts();
+ HSOpts.ModulesSkipDiagnosticOptions = true;
+ HSOpts.ModulesSkipHeaderSearchPaths = true;
+ HSOpts.ModulesSkipPragmaDiagnosticMappings = true;
+
PCHGenerator::HandleTranslationUnit(Ctx);
if (!isComplete())
diff --git a/clang/lib/Tooling/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt
index 91e6cbdc..8b4ab0e 100644
--- a/clang/lib/Tooling/CMakeLists.txt
+++ b/clang/lib/Tooling/CMakeLists.txt
@@ -53,14 +53,16 @@ else()
list(APPEND implicitDirs -I ${implicitDir})
endforeach()
+ setup_host_tool(clang-ast-dump CLANG_AST_DUMP clang_ast_dump_exe clang_ast_dump_target)
+
include(GetClangResourceDir)
get_clang_resource_dir(resource_dir PREFIX ${LLVM_BINARY_DIR})
add_custom_command(
COMMENT Generate ASTNodeAPI.json
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
- DEPENDS clang-ast-dump clang-resource-headers
+ DEPENDS ${clang_ast_dump_target} clang-resource-headers
COMMAND
- $<TARGET_FILE:clang-ast-dump>
+ ${clang_ast_dump_exe}
# Skip this in debug mode because parsing AST.h is too slow
--skip-processing=${skip_expensive_processing}
-I ${resource_dir}/include
diff --git a/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c b/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c
new file mode 100644
index 0000000..7839180
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c
@@ -0,0 +1,485 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -target-feature -fullfp16 -target-feature +v8a\
+// RUN: -flax-vector-conversions=none -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -passes=mem2reg \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -target-feature +fullfp16 -target-feature +v8.2a\
+// RUN: -flax-vector-conversions=none -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -passes=mem2reg \
+// RUN: | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_neon.h>
+
+// CHECK-LABEL: define {{[^@]+}}@test_vbsl_f16
+// CHECK-SAME: (<4 x i16> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]], <4 x half> noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[C]] to <8 x i8>
+// CHECK-NEXT: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
+// CHECK-NEXT: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
+// CHECK-NEXT: [[VBSL3_I:%.*]] = and <4 x i16> [[A]], [[VBSL1_I]]
+// CHECK-NEXT: [[TMP3:%.*]] = xor <4 x i16> [[A]], <i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK-NEXT: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK-NEXT: [[VBSL5_I:%.*]] = or <4 x i16> [[VBSL3_I]], [[VBSL4_I]]
+// CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i16> [[VBSL5_I]] to <4 x half>
+// CHECK-NEXT: ret <4 x half> [[TMP4]]
+//
+float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
+ return vbsl_f16(a, b, c);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vbslq_f16
+// CHECK-SAME: (<8 x i16> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]], <8 x half> noundef [[C:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[C]] to <16 x i8>
+// CHECK-NEXT: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
+// CHECK-NEXT: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
+// CHECK-NEXT: [[VBSL3_I:%.*]] = and <8 x i16> [[A]], [[VBSL1_I]]
+// CHECK-NEXT: [[TMP3:%.*]] = xor <8 x i16> [[A]], <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK-NEXT: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK-NEXT: [[VBSL5_I:%.*]] = or <8 x i16> [[VBSL3_I]], [[VBSL4_I]]
+// CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i16> [[VBSL5_I]] to <8 x half>
+// CHECK-NEXT: ret <8 x half> [[TMP4]]
+//
+float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
+ return vbslq_f16(a, b, c);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vzip_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T:%.*]], align 8
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-NEXT: [[VZIP_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK-NEXT: store <4 x half> [[VZIP_I]], ptr [[RETVAL_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[RETVAL_I]], i32 1
+// CHECK-NEXT: [[VZIP1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK-NEXT: store <4 x half> [[VZIP1_I]], ptr [[TMP2]], align 8
+// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL_I]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X4X2_T]] [[TMP3]], 0
+// CHECK-NEXT: store [2 x <4 x half>] [[TMP5]], ptr [[TMP4]], align 8
+// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], align 8
+// CHECK-NEXT: ret [[STRUCT_FLOAT16X4X2_T]] [[TMP6]]
+//
+float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
+ return vzip_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vzipq_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T:%.*]], align 16
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T]], align 16
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-NEXT: [[VZIP_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// CHECK-NEXT: store <8 x half> [[VZIP_I]], ptr [[RETVAL_I]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[RETVAL_I]], i32 1
+// CHECK-NEXT: [[VZIP1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+// CHECK-NEXT: store <8 x half> [[VZIP1_I]], ptr [[TMP2]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL_I]], align 16
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X8X2_T]] [[TMP3]], 0
+// CHECK-NEXT: store [2 x <8 x half>] [[TMP5]], ptr [[TMP4]], align 16
+// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], align 16
+// CHECK-NEXT: ret [[STRUCT_FLOAT16X8X2_T]] [[TMP6]]
+//
+float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
+ return vzipq_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vuzp_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T:%.*]], align 8
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-NEXT: [[VUZP_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK-NEXT: store <4 x half> [[VUZP_I]], ptr [[RETVAL_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[RETVAL_I]], i32 1
+// CHECK-NEXT: [[VUZP1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK-NEXT: store <4 x half> [[VUZP1_I]], ptr [[TMP2]], align 8
+// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL_I]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X4X2_T]] [[TMP3]], 0
+// CHECK-NEXT: store [2 x <4 x half>] [[TMP5]], ptr [[TMP4]], align 8
+// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], align 8
+// CHECK-NEXT: ret [[STRUCT_FLOAT16X4X2_T]] [[TMP6]]
+//
+float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
+ return vuzp_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vuzpq_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T:%.*]], align 16
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T]], align 16
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-NEXT: [[VUZP_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// CHECK-NEXT: store <8 x half> [[VUZP_I]], ptr [[RETVAL_I]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[RETVAL_I]], i32 1
+// CHECK-NEXT: [[VUZP1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+// CHECK-NEXT: store <8 x half> [[VUZP1_I]], ptr [[TMP2]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL_I]], align 16
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X8X2_T]] [[TMP3]], 0
+// CHECK-NEXT: store [2 x <8 x half>] [[TMP5]], ptr [[TMP4]], align 16
+// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], align 16
+// CHECK-NEXT: ret [[STRUCT_FLOAT16X8X2_T]] [[TMP6]]
+//
+float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
+ return vuzpq_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vtrn_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T:%.*]], align 8
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-NEXT: [[VTRN_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK-NEXT: store <4 x half> [[VTRN_I]], ptr [[RETVAL_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[RETVAL_I]], i32 1
+// CHECK-NEXT: [[VTRN1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK-NEXT: store <4 x half> [[VTRN1_I]], ptr [[TMP2]], align 8
+// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL_I]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X4X2_T]] [[TMP3]], 0
+// CHECK-NEXT: store [2 x <4 x half>] [[TMP5]], ptr [[TMP4]], align 8
+// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], align 8
+// CHECK-NEXT: ret [[STRUCT_FLOAT16X4X2_T]] [[TMP6]]
+//
+float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
+ return vtrn_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vtrnq_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T:%.*]], align 16
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T]], align 16
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-NEXT: [[VTRN_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// CHECK-NEXT: store <8 x half> [[VTRN_I]], ptr [[RETVAL_I]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[RETVAL_I]], i32 1
+// CHECK-NEXT: [[VTRN1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
+// CHECK-NEXT: store <8 x half> [[VTRN1_I]], ptr [[TMP2]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL_I]], align 16
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X8X2_T]] [[TMP3]], 0
+// CHECK-NEXT: store [2 x <8 x half>] [[TMP5]], ptr [[TMP4]], align 16
+// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], align 16
+// CHECK-NEXT: ret [[STRUCT_FLOAT16X8X2_T]] [[TMP6]]
+//
+float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
+ return vtrnq_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vmov_n_f16
+// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NEXT: ret <4 x half> [[VECINIT3]]
+//
+float16x4_t test_vmov_n_f16(float16_t a) {
+ return vmov_n_f16(a);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vmovq_n_f16
+// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
+// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
+// CHECK-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
+// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
+// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
+// CHECK-NEXT: ret <8 x half> [[VECINIT7]]
+//
+float16x8_t test_vmovq_n_f16(float16_t a) {
+ return vmovq_n_f16(a);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vdup_n_f16
+// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NEXT: ret <4 x half> [[VECINIT3]]
+//
+float16x4_t test_vdup_n_f16(float16_t a) {
+ return vdup_n_f16(a);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vdupq_n_f16
+// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
+// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
+// CHECK-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
+// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
+// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
+// CHECK-NEXT: ret <8 x half> [[VECINIT7]]
+//
+float16x8_t test_vdupq_n_f16(float16_t a) {
+ return vdupq_n_f16(a);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vdup_lane_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK-NEXT: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK-NEXT: ret <4 x half> [[LANE]]
+//
+float16x4_t test_vdup_lane_f16(float16x4_t a) {
+ return vdup_lane_f16(a, 3);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vdupq_lane_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK-NEXT: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK-NEXT: ret <8 x half> [[LANE]]
+//
+float16x8_t test_vdupq_lane_f16(float16x4_t a) {
+ return vdupq_lane_f16(a, 3);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vdup_laneq_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK-NEXT: [[LANE:%.*]] = shufflevector <8 x half> [[TMP1]], <8 x half> [[TMP1]], <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK-NEXT: ret <4 x half> [[LANE]]
+//
+float16x4_t test_vdup_laneq_f16(float16x8_t a) {
+ return vdup_laneq_f16(a, 1);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vdupq_laneq_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK-NEXT: [[LANE:%.*]] = shufflevector <8 x half> [[TMP1]], <8 x half> [[TMP1]], <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK-NEXT: ret <8 x half> [[LANE]]
+//
+float16x8_t test_vdupq_laneq_f16(float16x8_t a) {
+ return vdupq_laneq_f16(a, 7);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vext_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK-NEXT: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+// CHECK-NEXT: ret <4 x half> [[VEXT]]
+//
+float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
+ return vext_f16(a, b, 2);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vextq_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK-NEXT: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
+// CHECK-NEXT: ret <8 x half> [[VEXT]]
+//
+float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
+ return vextq_f16(a, b, 5);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vrev64_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[A]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vrev64_f16(float16x4_t a) {
+ return vrev64_f16(a);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vrev64q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[A]], <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vrev64q_f16(float16x8_t a) {
+ return vrev64q_f16(a);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vzip1_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vzip1_f16(float16x4_t a, float16x4_t b) {
+ return vzip1_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vzip1q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vzip1q_f16(float16x8_t a, float16x8_t b) {
+ return vzip1q_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vzip2_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vzip2_f16(float16x4_t a, float16x4_t b) {
+ return vzip2_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vzip2q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vzip2q_f16(float16x8_t a, float16x8_t b) {
+ return vzip2q_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vuzp1_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vuzp1_f16(float16x4_t a, float16x4_t b) {
+ return vuzp1_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vuzp1q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vuzp1q_f16(float16x8_t a, float16x8_t b) {
+ return vuzp1q_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vuzp2_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vuzp2_f16(float16x4_t a, float16x4_t b) {
+ return vuzp2_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vuzp2q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vuzp2q_f16(float16x8_t a, float16x8_t b) {
+ return vuzp2q_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vtrn1_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vtrn1_f16(float16x4_t a, float16x4_t b) {
+ return vtrn1_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vtrn1q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vtrn1q_f16(float16x8_t a, float16x8_t b) {
+ return vtrn1q_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vtrn2_f16
+// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vtrn2_f16(float16x4_t a, float16x4_t b) {
+ return vtrn2_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vtrn2q_f16
+// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
+// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vtrn2q_f16(float16x8_t a, float16x8_t b) {
+ return vtrn2q_f16(a, b);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vduph_laneq_f16
+// CHECK-SAME: (<8 x half> noundef [[VEC:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VGETQ_LANE:%.*]] = extractelement <8 x half> [[VEC]], i32 7
+// CHECK-NEXT: ret half [[VGETQ_LANE]]
+//
+float16_t test_vduph_laneq_f16(float16x8_t vec) {
+ return vduph_laneq_f16(vec, 7);
+}
+
+// CHECK-LABEL: define {{[^@]+}}@test_vduph_lane_f16
+// CHECK-SAME: (<4 x half> noundef [[VEC:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VGET_LANE:%.*]] = extractelement <4 x half> [[VEC]], i32 3
+// CHECK-NEXT: ret half [[VGET_LANE]]
+//
+float16_t test_vduph_lane_f16(float16x4_t vec) {
+ return vduph_lane_f16(vec, 3);
+}
diff --git a/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c b/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
index 4163e6e..617d515 100644
--- a/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
+++ b/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
@@ -2004,475 +2004,3 @@ float16_t test_vminnmv_f16(float16x4_t a) {
float16_t test_vminnmvq_f16(float16x8_t a) {
return vminnmvq_f16(a);
}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vbsl_f16
-// CHECK-SAME: (<4 x i16> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]], <4 x half> noundef [[C:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[C]] to <8 x i8>
-// CHECK-NEXT: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK-NEXT: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK-NEXT: [[VBSL3_I:%.*]] = and <4 x i16> [[A]], [[VBSL1_I]]
-// CHECK-NEXT: [[TMP3:%.*]] = xor <4 x i16> [[A]], <i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK-NEXT: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], [[VBSL2_I]]
-// CHECK-NEXT: [[VBSL5_I:%.*]] = or <4 x i16> [[VBSL3_I]], [[VBSL4_I]]
-// CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i16> [[VBSL5_I]] to <4 x half>
-// CHECK-NEXT: ret <4 x half> [[TMP4]]
-//
-float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
- return vbsl_f16(a, b, c);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vbslq_f16
-// CHECK-SAME: (<8 x i16> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]], <8 x half> noundef [[C:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[C]] to <16 x i8>
-// CHECK-NEXT: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK-NEXT: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK-NEXT: [[VBSL3_I:%.*]] = and <8 x i16> [[A]], [[VBSL1_I]]
-// CHECK-NEXT: [[TMP3:%.*]] = xor <8 x i16> [[A]], <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK-NEXT: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], [[VBSL2_I]]
-// CHECK-NEXT: [[VBSL5_I:%.*]] = or <8 x i16> [[VBSL3_I]], [[VBSL4_I]]
-// CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i16> [[VBSL5_I]] to <8 x half>
-// CHECK-NEXT: ret <8 x half> [[TMP4]]
-//
-float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
- return vbslq_f16(a, b, c);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vzip_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T:%.*]], align 8
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T]], align 8
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
-// CHECK-NEXT: [[VZIP_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK-NEXT: store <4 x half> [[VZIP_I]], ptr [[RETVAL_I]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[RETVAL_I]], i32 1
-// CHECK-NEXT: [[VZIP1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK-NEXT: store <4 x half> [[VZIP1_I]], ptr [[TMP2]], align 8
-// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL_I]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X4X2_T]] [[TMP3]], 0
-// CHECK-NEXT: store [2 x <4 x half>] [[TMP5]], ptr [[TMP4]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], align 8
-// CHECK-NEXT: ret [[STRUCT_FLOAT16X4X2_T]] [[TMP6]]
-//
-float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
- return vzip_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vzipq_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T:%.*]], align 16
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T]], align 16
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
-// CHECK-NEXT: [[VZIP_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK-NEXT: store <8 x half> [[VZIP_I]], ptr [[RETVAL_I]], align 16
-// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[RETVAL_I]], i32 1
-// CHECK-NEXT: [[VZIP1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK-NEXT: store <8 x half> [[VZIP1_I]], ptr [[TMP2]], align 16
-// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL_I]], align 16
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X8X2_T]] [[TMP3]], 0
-// CHECK-NEXT: store [2 x <8 x half>] [[TMP5]], ptr [[TMP4]], align 16
-// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], align 16
-// CHECK-NEXT: ret [[STRUCT_FLOAT16X8X2_T]] [[TMP6]]
-//
-float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
- return vzipq_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vuzp_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T:%.*]], align 8
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T]], align 8
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
-// CHECK-NEXT: [[VUZP_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK-NEXT: store <4 x half> [[VUZP_I]], ptr [[RETVAL_I]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[RETVAL_I]], i32 1
-// CHECK-NEXT: [[VUZP1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK-NEXT: store <4 x half> [[VUZP1_I]], ptr [[TMP2]], align 8
-// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL_I]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X4X2_T]] [[TMP3]], 0
-// CHECK-NEXT: store [2 x <4 x half>] [[TMP5]], ptr [[TMP4]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], align 8
-// CHECK-NEXT: ret [[STRUCT_FLOAT16X4X2_T]] [[TMP6]]
-//
-float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
- return vuzp_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vuzpq_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T:%.*]], align 16
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T]], align 16
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
-// CHECK-NEXT: [[VUZP_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK-NEXT: store <8 x half> [[VUZP_I]], ptr [[RETVAL_I]], align 16
-// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[RETVAL_I]], i32 1
-// CHECK-NEXT: [[VUZP1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK-NEXT: store <8 x half> [[VUZP1_I]], ptr [[TMP2]], align 16
-// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL_I]], align 16
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X8X2_T]] [[TMP3]], 0
-// CHECK-NEXT: store [2 x <8 x half>] [[TMP5]], ptr [[TMP4]], align 16
-// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], align 16
-// CHECK-NEXT: ret [[STRUCT_FLOAT16X8X2_T]] [[TMP6]]
-//
-float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
- return vuzpq_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vtrn_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T:%.*]], align 8
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X4X2_T]], align 8
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
-// CHECK-NEXT: [[VTRN_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK-NEXT: store <4 x half> [[VTRN_I]], ptr [[RETVAL_I]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[RETVAL_I]], i32 1
-// CHECK-NEXT: [[VTRN1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK-NEXT: store <4 x half> [[VTRN1_I]], ptr [[TMP2]], align 8
-// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL_I]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X4X2_T]] [[TMP3]], 0
-// CHECK-NEXT: store [2 x <4 x half>] [[TMP5]], ptr [[TMP4]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X4X2_T]], ptr [[RETVAL]], align 8
-// CHECK-NEXT: ret [[STRUCT_FLOAT16X4X2_T]] [[TMP6]]
-//
-float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
- return vtrn_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vtrnq_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL_I:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T:%.*]], align 16
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOAT16X8X2_T]], align 16
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
-// CHECK-NEXT: [[VTRN_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK-NEXT: store <8 x half> [[VTRN_I]], ptr [[RETVAL_I]], align 16
-// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[RETVAL_I]], i32 1
-// CHECK-NEXT: [[VTRN1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK-NEXT: store <8 x half> [[VTRN1_I]], ptr [[TMP2]], align 16
-// CHECK-NEXT: [[TMP3:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL_I]], align 16
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_FLOAT16X8X2_T]] [[TMP3]], 0
-// CHECK-NEXT: store [2 x <8 x half>] [[TMP5]], ptr [[TMP4]], align 16
-// CHECK-NEXT: [[TMP6:%.*]] = load [[STRUCT_FLOAT16X8X2_T]], ptr [[RETVAL]], align 16
-// CHECK-NEXT: ret [[STRUCT_FLOAT16X8X2_T]] [[TMP6]]
-//
-float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
- return vtrnq_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vmov_n_f16
-// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
-// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
-// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
-// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
-// CHECK-NEXT: ret <4 x half> [[VECINIT3]]
-//
-float16x4_t test_vmov_n_f16(float16_t a) {
- return vmov_n_f16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vmovq_n_f16
-// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
-// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
-// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
-// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
-// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
-// CHECK-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
-// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
-// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
-// CHECK-NEXT: ret <8 x half> [[VECINIT7]]
-//
-float16x8_t test_vmovq_n_f16(float16_t a) {
- return vmovq_n_f16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vdup_n_f16
-// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
-// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
-// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
-// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
-// CHECK-NEXT: ret <4 x half> [[VECINIT3]]
-//
-float16x4_t test_vdup_n_f16(float16_t a) {
- return vdup_n_f16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vdupq_n_f16
-// CHECK-SAME: (half noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
-// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
-// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
-// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
-// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
-// CHECK-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
-// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
-// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
-// CHECK-NEXT: ret <8 x half> [[VECINIT7]]
-//
-float16x8_t test_vdupq_n_f16(float16_t a) {
- return vdupq_n_f16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vdup_lane_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
-// CHECK-NEXT: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
-// CHECK-NEXT: ret <4 x half> [[LANE]]
-//
-float16x4_t test_vdup_lane_f16(float16x4_t a) {
- return vdup_lane_f16(a, 3);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vdupq_lane_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
-// CHECK-NEXT: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
-// CHECK-NEXT: ret <8 x half> [[LANE]]
-//
-float16x8_t test_vdupq_lane_f16(float16x4_t a) {
- return vdupq_lane_f16(a, 3);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vdup_laneq_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
-// CHECK-NEXT: [[LANE:%.*]] = shufflevector <8 x half> [[TMP1]], <8 x half> [[TMP1]], <4 x i32> <i32 1, i32 1, i32 1, i32 1>
-// CHECK-NEXT: ret <4 x half> [[LANE]]
-//
-float16x4_t test_vdup_laneq_f16(float16x8_t a) {
- return vdup_laneq_f16(a, 1);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vdupq_laneq_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
-// CHECK-NEXT: [[LANE:%.*]] = shufflevector <8 x half> [[TMP1]], <8 x half> [[TMP1]], <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
-// CHECK-NEXT: ret <8 x half> [[LANE]]
-//
-float16x8_t test_vdupq_laneq_f16(float16x8_t a) {
- return vdupq_laneq_f16(a, 7);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vext_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
-// CHECK-NEXT: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
-// CHECK-NEXT: ret <4 x half> [[VEXT]]
-//
-float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
- return vext_f16(a, b, 2);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vextq_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
-// CHECK-NEXT: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
-// CHECK-NEXT: ret <8 x half> [[VEXT]]
-//
-float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
- return vextq_f16(a, b, 5);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vrev64_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[A]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vrev64_f16(float16x4_t a) {
- return vrev64_f16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vrev64q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[A]], <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vrev64q_f16(float16x8_t a) {
- return vrev64q_f16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vzip1_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vzip1_f16(float16x4_t a, float16x4_t b) {
- return vzip1_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vzip1q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vzip1q_f16(float16x8_t a, float16x8_t b) {
- return vzip1q_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vzip2_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vzip2_f16(float16x4_t a, float16x4_t b) {
- return vzip2_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vzip2q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vzip2q_f16(float16x8_t a, float16x8_t b) {
- return vzip2q_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vuzp1_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vuzp1_f16(float16x4_t a, float16x4_t b) {
- return vuzp1_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vuzp1q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vuzp1q_f16(float16x8_t a, float16x8_t b) {
- return vuzp1q_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vuzp2_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vuzp2_f16(float16x4_t a, float16x4_t b) {
- return vuzp2_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vuzp2q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vuzp2q_f16(float16x8_t a, float16x8_t b) {
- return vuzp2q_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vtrn1_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vtrn1_f16(float16x4_t a, float16x4_t b) {
- return vtrn1_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vtrn1q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vtrn1q_f16(float16x8_t a, float16x8_t b) {
- return vtrn1q_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vtrn2_f16
-// CHECK-SAME: (<4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK-NEXT: ret <4 x half> [[SHUFFLE_I]]
-//
-float16x4_t test_vtrn2_f16(float16x4_t a, float16x4_t b) {
- return vtrn2_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vtrn2q_f16
-// CHECK-SAME: (<8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]]
-//
-float16x8_t test_vtrn2q_f16(float16x8_t a, float16x8_t b) {
- return vtrn2q_f16(a, b);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vduph_laneq_f16
-// CHECK-SAME: (<8 x half> noundef [[VEC:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[VGETQ_LANE:%.*]] = extractelement <8 x half> [[VEC]], i32 7
-// CHECK-NEXT: ret half [[VGETQ_LANE]]
-//
-float16_t test_vduph_laneq_f16(float16x8_t vec) {
- return vduph_laneq_f16(vec, 7);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vduph_lane_f16
-// CHECK-SAME: (<4 x half> noundef [[VEC:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[VGET_LANE:%.*]] = extractelement <4 x half> [[VEC]], i32 3
-// CHECK-NEXT: ret half [[VGET_LANE]]
-//
-float16_t test_vduph_lane_f16(float16x4_t vec) {
- return vduph_lane_f16(vec, 3);
-}
diff --git a/clang/test/CodeGen/allow-ubsan-check.c b/clang/test/CodeGen/allow-ubsan-check.c
new file mode 100644
index 0000000..bc42523
--- /dev/null
+++ b/clang/test/CodeGen/allow-ubsan-check.c
@@ -0,0 +1,207 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -fsanitize-trap=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=TRAP
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=RECOVER
+
+
+// CHECK-LABEL: define dso_local i32 @div(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0, !nosanitize [[META2:![0-9]+]]
+// CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0]], -2147483648, !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP1]], -1, !nosanitize [[META2]]
+// CHECK-NEXT: [[OR:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[OR]], !nosanitize [[META2]]
+// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_DIVREM_OVERFLOW:%.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
+// CHECK: handler.divrem_overflow:
+// CHECK-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
+// CHECK-NEXT: call void @__ubsan_handle_divrem_overflow_abort(ptr @[[GLOB1:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3:[0-9]+]], !nosanitize [[META2]]
+// CHECK-NEXT: unreachable, !nosanitize [[META2]]
+// CHECK: cont:
+// CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: ret i32 [[DIV]]
+//
+// TRAP-LABEL: define dso_local i32 @div(
+// TRAP-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
+// TRAP-NEXT: entry:
+// TRAP-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// TRAP-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
+// TRAP-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// TRAP-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// TRAP-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// TRAP-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// TRAP-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0, !nosanitize [[META2:![0-9]+]]
+// TRAP-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0]], -2147483648, !nosanitize [[META2]]
+// TRAP-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP1]], -1, !nosanitize [[META2]]
+// TRAP-NEXT: [[OR:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META2]]
+// TRAP-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[OR]], !nosanitize [[META2]]
+// TRAP-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !nosanitize [[META2]]
+// TRAP: trap:
+// TRAP-NEXT: call void @llvm.ubsantrap(i8 3) #[[ATTR3:[0-9]+]], !nosanitize [[META2]]
+// TRAP-NEXT: unreachable, !nosanitize [[META2]]
+// TRAP: cont:
+// TRAP-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
+// TRAP-NEXT: ret i32 [[DIV]]
+//
+// RECOVER-LABEL: define dso_local i32 @div(
+// RECOVER-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
+// RECOVER-NEXT: entry:
+// RECOVER-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// RECOVER-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
+// RECOVER-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// RECOVER-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// RECOVER-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// RECOVER-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// RECOVER-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0, !nosanitize [[META2:![0-9]+]]
+// RECOVER-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0]], -2147483648, !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP1]], -1, !nosanitize [[META2]]
+// RECOVER-NEXT: [[OR:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[OR]], !nosanitize [[META2]]
+// RECOVER-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_DIVREM_OVERFLOW:%.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
+// RECOVER: handler.divrem_overflow:
+// RECOVER-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
+// RECOVER-NEXT: call void @__ubsan_handle_divrem_overflow(ptr @[[GLOB1:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3:[0-9]+]], !nosanitize [[META2]]
+// RECOVER-NEXT: br label [[CONT]], !nosanitize [[META2]]
+// RECOVER: cont:
+// RECOVER-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
+// RECOVER-NEXT: ret i32 [[DIV]]
+//
+int div(int x, int y) {
+ return x / y;
+}
+
+// CHECK-LABEL: define dso_local i32 @null(
+// CHECK-SAME: ptr noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 8
+// CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, !nosanitize [[META2]]
+// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[HANDLER_TYPE_MISMATCH:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
+// CHECK: handler.type_mismatch:
+// CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META2]]
+// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort(ptr @[[GLOB2:[0-9]+]], i64 [[TMP2]]) #[[ATTR3]], !nosanitize [[META2]]
+// CHECK-NEXT: unreachable, !nosanitize [[META2]]
+// CHECK: cont:
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+// TRAP-LABEL: define dso_local i32 @null(
+// TRAP-SAME: ptr noundef [[X:%.*]]) #[[ATTR0]] {
+// TRAP-NEXT: entry:
+// TRAP-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8
+// TRAP-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 8
+// TRAP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 8
+// TRAP-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, !nosanitize [[META2]]
+// TRAP-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !nosanitize [[META2]]
+// TRAP: trap:
+// TRAP-NEXT: call void @llvm.ubsantrap(i8 22) #[[ATTR3]], !nosanitize [[META2]]
+// TRAP-NEXT: unreachable, !nosanitize [[META2]]
+// TRAP: cont:
+// TRAP-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP0]], align 4
+// TRAP-NEXT: ret i32 [[TMP2]]
+//
+// RECOVER-LABEL: define dso_local i32 @null(
+// RECOVER-SAME: ptr noundef [[X:%.*]]) #[[ATTR0]] {
+// RECOVER-NEXT: entry:
+// RECOVER-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8
+// RECOVER-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 8
+// RECOVER-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 8
+// RECOVER-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, !nosanitize [[META2]]
+// RECOVER-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[HANDLER_TYPE_MISMATCH:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
+// RECOVER: handler.type_mismatch:
+// RECOVER-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META2]]
+// RECOVER-NEXT: call void @__ubsan_handle_type_mismatch_v1(ptr @[[GLOB2:[0-9]+]], i64 [[TMP2]]) #[[ATTR3]], !nosanitize [[META2]]
+// RECOVER-NEXT: br label [[CONT]], !nosanitize [[META2]]
+// RECOVER: cont:
+// RECOVER-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4
+// RECOVER-NEXT: ret i32 [[TMP3]]
+//
+int null(int* x) {
+ return *x;
+}
+
+// CHECK-LABEL: define dso_local i32 @overflow(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP0]], i32 [[TMP1]]), !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true, !nosanitize [[META2]]
+// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_ADD_OVERFLOW:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
+// CHECK: handler.add_overflow:
+// CHECK-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
+// CHECK-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
+// CHECK-NEXT: call void @__ubsan_handle_add_overflow_abort(ptr @[[GLOB3:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3]], !nosanitize [[META2]]
+// CHECK-NEXT: unreachable, !nosanitize [[META2]]
+// CHECK: cont:
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+// TRAP-LABEL: define dso_local i32 @overflow(
+// TRAP-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// TRAP-NEXT: entry:
+// TRAP-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// TRAP-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
+// TRAP-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// TRAP-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// TRAP-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// TRAP-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// TRAP-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP0]], i32 [[TMP1]]), !nosanitize [[META2]]
+// TRAP-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]]
+// TRAP-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]]
+// TRAP-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true, !nosanitize [[META2]]
+// TRAP-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !nosanitize [[META2]]
+// TRAP: trap:
+// TRAP-NEXT: call void @llvm.ubsantrap(i8 0) #[[ATTR3]], !nosanitize [[META2]]
+// TRAP-NEXT: unreachable, !nosanitize [[META2]]
+// TRAP: cont:
+// TRAP-NEXT: ret i32 [[TMP3]]
+//
+// RECOVER-LABEL: define dso_local i32 @overflow(
+// RECOVER-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// RECOVER-NEXT: entry:
+// RECOVER-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// RECOVER-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
+// RECOVER-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// RECOVER-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// RECOVER-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// RECOVER-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// RECOVER-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP0]], i32 [[TMP1]]), !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true, !nosanitize [[META2]]
+// RECOVER-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_ADD_OVERFLOW:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
+// RECOVER: handler.add_overflow:
+// RECOVER-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
+// RECOVER-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
+// RECOVER-NEXT: call void @__ubsan_handle_add_overflow(ptr @[[GLOB3:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3]], !nosanitize [[META2]]
+// RECOVER-NEXT: br label [[CONT]], !nosanitize [[META2]]
+// RECOVER: cont:
+// RECOVER-NEXT: ret i32 [[TMP3]]
+//
+int overflow(int x, int y) {
+ return x + y;
+}
+//.
+// CHECK: [[META2]] = !{}
+// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
+//.
+// TRAP: [[META2]] = !{}
+//.
+// RECOVER: [[META2]] = !{}
+// RECOVER: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
+//.
diff --git a/clang/test/CodeGen/arm-v8.2a-neon-intrinsics-generic.c b/clang/test/CodeGen/arm-v8.2a-neon-intrinsics-generic.c
new file mode 100644
index 0000000..f8d8333
--- /dev/null
+++ b/clang/test/CodeGen/arm-v8.2a-neon-intrinsics-generic.c
@@ -0,0 +1,600 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple armv8.2a-linux-gnu -target-abi apcs-gnu -target-feature +neon -target-feature -fullfp16 \
+// RUN: -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -passes=sroa \
+// RUN: | FileCheck %s --check-prefixes=CHECK-NOFP16
+// RUN: %clang_cc1 -triple armv8a-linux-gnu -target-abi apcs-gnu -target-feature +neon -target-feature +fullfp16 \
+// RUN: -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -passes=sroa \
+// RUN: | FileCheck %s --check-prefixes=CHECK-FP16
+
+// REQUIRES: arm-registered-target
+
+#include <arm_neon.h>
+
+// CHECK-NOFP16-LABEL: define dso_local <2 x i32> @test_vbsl_f16(
+// CHECK-NOFP16-SAME: <4 x i16> noundef [[A:%.*]], <2 x i32> noundef [[B_COERCE:%.*]], <2 x i32> noundef [[C_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[B_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[C_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[TMP0]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x half> [[TMP1]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP2]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP3]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <4 x half> [[TMP4]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[VBSL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> [[TMP6]], <8 x i8> [[TMP7]], <8 x i8> [[TMP8]])
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <8 x i8> [[VBSL_V_I]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP11:%.*]] = bitcast <2 x i32> [[TMP10]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP12:%.*]] = bitcast <4 x half> [[TMP11]] to <2 x i32>
+// CHECK-NOFP16-NEXT: ret <2 x i32> [[TMP12]]
+//
+// CHECK-FP16-LABEL: define dso_local <4 x half> @test_vbsl_f16(
+// CHECK-FP16-SAME: <4 x i16> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]], <4 x half> noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[C]] to <8 x i8>
+// CHECK-FP16-NEXT: [[VBSL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i8> [[TMP2]])
+// CHECK-FP16-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[VBSL_V_I]] to <4 x half>
+// CHECK-FP16-NEXT: ret <4 x half> [[TMP3]]
+//
+float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
+ return vbsl_f16(a, b, c);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <4 x i32> @test_vbslq_f16(
+// CHECK-NOFP16-SAME: <8 x i16> noundef [[A:%.*]], <4 x i32> noundef [[B_COERCE:%.*]], <4 x i32> noundef [[C_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[B_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[C_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[TMP0]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x half> [[TMP1]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[VBSLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> [[TMP6]], <16 x i8> [[TMP7]], <16 x i8> [[TMP8]])
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <16 x i8> [[VBSLQ_V_I]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP12:%.*]] = bitcast <8 x half> [[TMP11]] to <4 x i32>
+// CHECK-NOFP16-NEXT: ret <4 x i32> [[TMP12]]
+//
+// CHECK-FP16-LABEL: define dso_local <8 x half> @test_vbslq_f16(
+// CHECK-FP16-SAME: <8 x i16> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]], <8 x half> noundef [[C:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[C]] to <16 x i8>
+// CHECK-FP16-NEXT: [[VBSLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[TMP2]])
+// CHECK-FP16-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[VBSLQ_V_I]] to <8 x half>
+// CHECK-FP16-NEXT: ret <8 x half> [[TMP3]]
+//
+float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
+ return vbslq_f16(a, b, c);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local void @test_vzip_f16(
+// CHECK-NOFP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X4X2_T:%.*]]) align 8 [[AGG_RESULT:%.*]], <2 x i32> noundef [[A_COERCE:%.*]], <2 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[B_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[TMP0]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x half> [[TMP1]] to <2 x i32>
+// CHECK-NOFP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP2]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP3]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <4 x half> [[TMP4]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK-NOFP16-NEXT: store <4 x i16> [[VZIP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META3]]
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = getelementptr inbounds <4 x i16>, ptr [[AGG_RESULT]], i32 1
+// CHECK-NOFP16-NEXT: [[VZIP3_I:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK-NOFP16-NEXT: store <4 x i16> [[VZIP3_I]], ptr [[TMP10]], align 4, !alias.scope [[META3]]
+// CHECK-NOFP16-NEXT: ret void
+//
+// CHECK-FP16-LABEL: define dso_local void @test_vzip_f16(
+// CHECK-FP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X4X2_T:%.*]]) align 8 [[AGG_RESULT:%.*]], <4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-FP16-NEXT: [[VZIP_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK-FP16-NEXT: store <4 x half> [[VZIP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META3]]
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[AGG_RESULT]], i32 1
+// CHECK-FP16-NEXT: [[VZIP1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK-FP16-NEXT: store <4 x half> [[VZIP1_I]], ptr [[TMP2]], align 4, !alias.scope [[META3]]
+// CHECK-FP16-NEXT: ret void
+//
+float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
+ return vzip_f16(a, b);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local void @test_vzipq_f16(
+// CHECK-NOFP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X8X2_T:%.*]]) align 16 [[AGG_RESULT:%.*]], <4 x i32> noundef [[A_COERCE:%.*]], <4 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[TMP0]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x half> [[TMP1]] to <4 x i32>
+// CHECK-NOFP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// CHECK-NOFP16-NEXT: store <8 x i16> [[VZIP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META6]]
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = getelementptr inbounds <8 x i16>, ptr [[AGG_RESULT]], i32 1
+// CHECK-NOFP16-NEXT: [[VZIP3_I:%.*]] = shufflevector <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+// CHECK-NOFP16-NEXT: store <8 x i16> [[VZIP3_I]], ptr [[TMP10]], align 4, !alias.scope [[META6]]
+// CHECK-NOFP16-NEXT: ret void
+//
+// CHECK-FP16-LABEL: define dso_local void @test_vzipq_f16(
+// CHECK-FP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X8X2_T:%.*]]) align 16 [[AGG_RESULT:%.*]], <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-FP16-NEXT: [[VZIP_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// CHECK-FP16-NEXT: store <8 x half> [[VZIP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META6]]
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[AGG_RESULT]], i32 1
+// CHECK-FP16-NEXT: [[VZIP1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+// CHECK-FP16-NEXT: store <8 x half> [[VZIP1_I]], ptr [[TMP2]], align 4, !alias.scope [[META6]]
+// CHECK-FP16-NEXT: ret void
+//
+float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
+ return vzipq_f16(a, b);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local void @test_vuzp_f16(
+// CHECK-NOFP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X4X2_T:%.*]]) align 8 [[AGG_RESULT:%.*]], <2 x i32> noundef [[A_COERCE:%.*]], <2 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[B_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[TMP0]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x half> [[TMP1]] to <2 x i32>
+// CHECK-NOFP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP2]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP3]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <4 x half> [[TMP4]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK-NOFP16-NEXT: store <4 x i16> [[VUZP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META9]]
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = getelementptr inbounds <4 x i16>, ptr [[AGG_RESULT]], i32 1
+// CHECK-NOFP16-NEXT: [[VUZP3_I:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK-NOFP16-NEXT: store <4 x i16> [[VUZP3_I]], ptr [[TMP10]], align 4, !alias.scope [[META9]]
+// CHECK-NOFP16-NEXT: ret void
+//
+// CHECK-FP16-LABEL: define dso_local void @test_vuzp_f16(
+// CHECK-FP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X4X2_T:%.*]]) align 8 [[AGG_RESULT:%.*]], <4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-FP16-NEXT: [[VUZP_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK-FP16-NEXT: store <4 x half> [[VUZP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META9]]
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[AGG_RESULT]], i32 1
+// CHECK-FP16-NEXT: [[VUZP1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK-FP16-NEXT: store <4 x half> [[VUZP1_I]], ptr [[TMP2]], align 4, !alias.scope [[META9]]
+// CHECK-FP16-NEXT: ret void
+//
+float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
+ return vuzp_f16(a, b);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local void @test_vuzpq_f16(
+// CHECK-NOFP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X8X2_T:%.*]]) align 16 [[AGG_RESULT:%.*]], <4 x i32> noundef [[A_COERCE:%.*]], <4 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[TMP0]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x half> [[TMP1]] to <4 x i32>
+// CHECK-NOFP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]])
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// CHECK-NOFP16-NEXT: store <8 x i16> [[VUZP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META12]]
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = getelementptr inbounds <8 x i16>, ptr [[AGG_RESULT]], i32 1
+// CHECK-NOFP16-NEXT: [[VUZP3_I:%.*]] = shufflevector <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+// CHECK-NOFP16-NEXT: store <8 x i16> [[VUZP3_I]], ptr [[TMP10]], align 4, !alias.scope [[META12]]
+// CHECK-NOFP16-NEXT: ret void
+//
+// CHECK-FP16-LABEL: define dso_local void @test_vuzpq_f16(
+// CHECK-FP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X8X2_T:%.*]]) align 16 [[AGG_RESULT:%.*]], <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]])
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-FP16-NEXT: [[VUZP_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// CHECK-FP16-NEXT: store <8 x half> [[VUZP_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META12]]
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[AGG_RESULT]], i32 1
+// CHECK-FP16-NEXT: [[VUZP1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+// CHECK-FP16-NEXT: store <8 x half> [[VUZP1_I]], ptr [[TMP2]], align 4, !alias.scope [[META12]]
+// CHECK-FP16-NEXT: ret void
+//
+float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
+ return vuzpq_f16(a, b);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local void @test_vtrn_f16(
+// CHECK-NOFP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X4X2_T:%.*]]) align 8 [[AGG_RESULT:%.*]], <2 x i32> noundef [[A_COERCE:%.*]], <2 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[B_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[TMP0]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x half> [[TMP1]] to <2 x i32>
+// CHECK-NOFP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META15:![0-9]+]])
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP2]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP3]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <4 x half> [[TMP4]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK-NOFP16-NEXT: store <4 x i16> [[VTRN_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META15]]
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = getelementptr inbounds <4 x i16>, ptr [[AGG_RESULT]], i32 1
+// CHECK-NOFP16-NEXT: [[VTRN3_I:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK-NOFP16-NEXT: store <4 x i16> [[VTRN3_I]], ptr [[TMP10]], align 4, !alias.scope [[META15]]
+// CHECK-NOFP16-NEXT: ret void
+//
+// CHECK-FP16-LABEL: define dso_local void @test_vtrn_f16(
+// CHECK-FP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X4X2_T:%.*]]) align 8 [[AGG_RESULT:%.*]], <4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META15:![0-9]+]])
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-FP16-NEXT: [[VTRN_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK-FP16-NEXT: store <4 x half> [[VTRN_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META15]]
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, ptr [[AGG_RESULT]], i32 1
+// CHECK-FP16-NEXT: [[VTRN1_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[B]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK-FP16-NEXT: store <4 x half> [[VTRN1_I]], ptr [[TMP2]], align 4, !alias.scope [[META15]]
+// CHECK-FP16-NEXT: ret void
+//
+float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
+ return vtrn_f16(a, b);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local void @test_vtrnq_f16(
+// CHECK-NOFP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X8X2_T:%.*]]) align 16 [[AGG_RESULT:%.*]], <4 x i32> noundef [[A_COERCE:%.*]], <4 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[TMP0]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x half> [[TMP1]] to <4 x i32>
+// CHECK-NOFP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META18:![0-9]+]])
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// CHECK-NOFP16-NEXT: store <8 x i16> [[VTRN_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META18]]
+// CHECK-NOFP16-NEXT: [[TMP10:%.*]] = getelementptr inbounds <8 x i16>, ptr [[AGG_RESULT]], i32 1
+// CHECK-NOFP16-NEXT: [[VTRN3_I:%.*]] = shufflevector <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
+// CHECK-NOFP16-NEXT: store <8 x i16> [[VTRN3_I]], ptr [[TMP10]], align 4, !alias.scope [[META18]]
+// CHECK-NOFP16-NEXT: ret void
+//
+// CHECK-FP16-LABEL: define dso_local void @test_vtrnq_f16(
+// CHECK-FP16-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16X8X2_T:%.*]]) align 16 [[AGG_RESULT:%.*]], <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META18:![0-9]+]])
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-FP16-NEXT: [[VTRN_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// CHECK-FP16-NEXT: store <8 x half> [[VTRN_I]], ptr [[AGG_RESULT]], align 4, !alias.scope [[META18]]
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, ptr [[AGG_RESULT]], i32 1
+// CHECK-FP16-NEXT: [[VTRN1_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[B]], <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
+// CHECK-FP16-NEXT: store <8 x half> [[VTRN1_I]], ptr [[TMP2]], align 4, !alias.scope [[META18]]
+// CHECK-FP16-NEXT: ret void
+//
+float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
+ return vtrnq_f16(a, b);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <2 x i32> @test_vmov_n_f16(
+// CHECK-NOFP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-NOFP16-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NOFP16-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NOFP16-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[VECINIT3]] to <2 x i32>
+// CHECK-NOFP16-NEXT: ret <2 x i32> [[TMP0]]
+//
+// CHECK-FP16-LABEL: define dso_local <4 x half> @test_vmov_n_f16(
+// CHECK-FP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-FP16-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-FP16-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-FP16-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-FP16-NEXT: ret <4 x half> [[VECINIT3]]
+//
+float16x4_t test_vmov_n_f16(float16_t a) {
+ return vmov_n_f16(a);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <4 x i32> @test_vmovq_n_f16(
+// CHECK-NOFP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
+// CHECK-NOFP16-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NOFP16-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NOFP16-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NOFP16-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
+// CHECK-NOFP16-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
+// CHECK-NOFP16-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
+// CHECK-NOFP16-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[VECINIT7]] to <4 x i32>
+// CHECK-NOFP16-NEXT: ret <4 x i32> [[TMP0]]
+//
+// CHECK-FP16-LABEL: define dso_local <8 x half> @test_vmovq_n_f16(
+// CHECK-FP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
+// CHECK-FP16-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-FP16-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-FP16-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-FP16-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
+// CHECK-FP16-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
+// CHECK-FP16-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
+// CHECK-FP16-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
+// CHECK-FP16-NEXT: ret <8 x half> [[VECINIT7]]
+//
+float16x8_t test_vmovq_n_f16(float16_t a) {
+ return vmovq_n_f16(a);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <2 x i32> @test_vdup_n_f16(
+// CHECK-NOFP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-NOFP16-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NOFP16-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NOFP16-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[VECINIT3]] to <2 x i32>
+// CHECK-NOFP16-NEXT: ret <2 x i32> [[TMP0]]
+//
+// CHECK-FP16-LABEL: define dso_local <4 x half> @test_vdup_n_f16(
+// CHECK-FP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[VECINIT:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-FP16-NEXT: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-FP16-NEXT: [[VECINIT2:%.*]] = insertelement <4 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-FP16-NEXT: [[VECINIT3:%.*]] = insertelement <4 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-FP16-NEXT: ret <4 x half> [[VECINIT3]]
+//
+float16x4_t test_vdup_n_f16(float16_t a) {
+ return vdup_n_f16(a);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <4 x i32> @test_vdupq_n_f16(
+// CHECK-NOFP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
+// CHECK-NOFP16-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-NOFP16-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-NOFP16-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-NOFP16-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
+// CHECK-NOFP16-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
+// CHECK-NOFP16-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
+// CHECK-NOFP16-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[VECINIT7]] to <4 x i32>
+// CHECK-NOFP16-NEXT: ret <4 x i32> [[TMP0]]
+//
+// CHECK-FP16-LABEL: define dso_local <8 x half> @test_vdupq_n_f16(
+// CHECK-FP16-SAME: half noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[VECINIT:%.*]] = insertelement <8 x half> poison, half [[A]], i32 0
+// CHECK-FP16-NEXT: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[A]], i32 1
+// CHECK-FP16-NEXT: [[VECINIT2:%.*]] = insertelement <8 x half> [[VECINIT1]], half [[A]], i32 2
+// CHECK-FP16-NEXT: [[VECINIT3:%.*]] = insertelement <8 x half> [[VECINIT2]], half [[A]], i32 3
+// CHECK-FP16-NEXT: [[VECINIT4:%.*]] = insertelement <8 x half> [[VECINIT3]], half [[A]], i32 4
+// CHECK-FP16-NEXT: [[VECINIT5:%.*]] = insertelement <8 x half> [[VECINIT4]], half [[A]], i32 5
+// CHECK-FP16-NEXT: [[VECINIT6:%.*]] = insertelement <8 x half> [[VECINIT5]], half [[A]], i32 6
+// CHECK-FP16-NEXT: [[VECINIT7:%.*]] = insertelement <8 x half> [[VECINIT6]], half [[A]], i32 7
+// CHECK-FP16-NEXT: ret <8 x half> [[VECINIT7]]
+//
+float16x8_t test_vdupq_n_f16(float16_t a) {
+ return vdupq_n_f16(a);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <2 x i32> @test_vdup_lane_f16(
+// CHECK-NOFP16-SAME: <2 x i32> noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[TMP0]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x i16> [[LANE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <2 x i32>
+// CHECK-NOFP16-NEXT: ret <2 x i32> [[TMP4]]
+//
+// CHECK-FP16-LABEL: define dso_local <4 x half> @test_vdup_lane_f16(
+// CHECK-FP16-SAME: <4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK-FP16-NEXT: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK-FP16-NEXT: ret <4 x half> [[LANE]]
+//
+float16x4_t test_vdup_lane_f16(float16x4_t a) {
+ return vdup_lane_f16(a, 3);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <4 x i32> @test_vdupq_lane_f16(
+// CHECK-NOFP16-SAME: <2 x i32> noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[TMP0]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[LANE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <4 x i32>
+// CHECK-NOFP16-NEXT: ret <4 x i32> [[TMP4]]
+//
+// CHECK-FP16-LABEL: define dso_local <8 x half> @test_vdupq_lane_f16(
+// CHECK-FP16-SAME: <4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK-FP16-NEXT: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK-FP16-NEXT: ret <8 x half> [[LANE]]
+//
+float16x8_t test_vdupq_lane_f16(float16x4_t a) {
+ return vdupq_lane_f16(a, 3);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <2 x i32> @test_vext_f16(
+// CHECK-NOFP16-SAME: <2 x i32> noundef [[A_COERCE:%.*]], <2 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[B_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <4 x half> [[TMP0]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x half> [[TMP1]] to <8 x i8>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
+// CHECK-NOFP16-NEXT: [[VEXT:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[VEXT]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <4 x half> [[TMP6]] to <2 x i32>
+// CHECK-NOFP16-NEXT: ret <2 x i32> [[TMP7]]
+//
+// CHECK-FP16-LABEL: define dso_local <4 x half> @test_vext_f16(
+// CHECK-FP16-SAME: <4 x half> noundef [[A:%.*]], <4 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[B]] to <8 x i8>
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK-FP16-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK-FP16-NEXT: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+// CHECK-FP16-NEXT: ret <4 x half> [[VEXT]]
+//
+float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
+ return vext_f16(a, b, 2);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <4 x i32> @test_vextq_f16(
+// CHECK-NOFP16-SAME: <4 x i32> noundef [[A_COERCE:%.*]], <4 x i32> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <8 x half> [[TMP0]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x half> [[TMP1]] to <16 x i8>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP3]] to <8 x i16>
+// CHECK-NOFP16-NEXT: [[VEXT:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
+// CHECK-NOFP16-NEXT: [[TMP6:%.*]] = bitcast <8 x i16> [[VEXT]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <4 x i32>
+// CHECK-NOFP16-NEXT: ret <4 x i32> [[TMP7]]
+//
+// CHECK-FP16-LABEL: define dso_local <8 x half> @test_vextq_f16(
+// CHECK-FP16-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[A]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[B]] to <16 x i8>
+// CHECK-FP16-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK-FP16-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK-FP16-NEXT: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
+// CHECK-FP16-NEXT: ret <8 x half> [[VEXT]]
+//
+float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
+ return vextq_f16(a, b, 5);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <2 x i32> @test_vrev64_f16(
+// CHECK-NOFP16-SAME: <2 x i32> noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A_COERCE]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <4 x half> [[TMP0]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[TMP1]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP2]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <4 x half> [[SHUFFLE_I]] to <2 x i32>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <4 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <4 x half> [[TMP4]] to <2 x i32>
+// CHECK-NOFP16-NEXT: ret <2 x i32> [[TMP5]]
+//
+// CHECK-FP16-LABEL: define dso_local <4 x half> @test_vrev64_f16(
+// CHECK-FP16-SAME: <4 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[A]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// CHECK-FP16-NEXT: ret <4 x half> [[SHUFFLE_I]]
+//
+float16x4_t test_vrev64_f16(float16x4_t a) {
+ return vrev64_f16(a);
+}
+
+// CHECK-NOFP16-LABEL: define dso_local <4 x i32> @test_vrev64q_f16(
+// CHECK-NOFP16-SAME: <4 x i32> noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NOFP16-NEXT: entry:
+// CHECK-NOFP16-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A_COERCE]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP1:%.*]] = bitcast <8 x half> [[TMP0]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP1]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP2]], <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+// CHECK-NOFP16-NEXT: [[TMP3:%.*]] = bitcast <8 x half> [[SHUFFLE_I]] to <4 x i32>
+// CHECK-NOFP16-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x half>
+// CHECK-NOFP16-NEXT: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <4 x i32>
+// CHECK-NOFP16-NEXT: ret <4 x i32> [[TMP5]]
+//
+// CHECK-FP16-LABEL: define dso_local <8 x half> @test_vrev64q_f16(
+// CHECK-FP16-SAME: <8 x half> noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK-FP16-NEXT: entry:
+// CHECK-FP16-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[A]], <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+// CHECK-FP16-NEXT: ret <8 x half> [[SHUFFLE_I]]
+//
+float16x8_t test_vrev64q_f16(float16x8_t a) {
+ return vrev64q_f16(a);
+}
+//.
+// CHECK-NOFP16: [[META3]] = !{[[META4:![0-9]+]]}
+// CHECK-NOFP16: [[META4]] = distinct !{[[META4]], [[META5:![0-9]+]], !"vzip_f16: %agg.result"}
+// CHECK-NOFP16: [[META5]] = distinct !{[[META5]], !"vzip_f16"}
+// CHECK-NOFP16: [[META6]] = !{[[META7:![0-9]+]]}
+// CHECK-NOFP16: [[META7]] = distinct !{[[META7]], [[META8:![0-9]+]], !"vzipq_f16: %agg.result"}
+// CHECK-NOFP16: [[META8]] = distinct !{[[META8]], !"vzipq_f16"}
+// CHECK-NOFP16: [[META9]] = !{[[META10:![0-9]+]]}
+// CHECK-NOFP16: [[META10]] = distinct !{[[META10]], [[META11:![0-9]+]], !"vuzp_f16: %agg.result"}
+// CHECK-NOFP16: [[META11]] = distinct !{[[META11]], !"vuzp_f16"}
+// CHECK-NOFP16: [[META12]] = !{[[META13:![0-9]+]]}
+// CHECK-NOFP16: [[META13]] = distinct !{[[META13]], [[META14:![0-9]+]], !"vuzpq_f16: %agg.result"}
+// CHECK-NOFP16: [[META14]] = distinct !{[[META14]], !"vuzpq_f16"}
+// CHECK-NOFP16: [[META15]] = !{[[META16:![0-9]+]]}
+// CHECK-NOFP16: [[META16]] = distinct !{[[META16]], [[META17:![0-9]+]], !"vtrn_f16: %agg.result"}
+// CHECK-NOFP16: [[META17]] = distinct !{[[META17]], !"vtrn_f16"}
+// CHECK-NOFP16: [[META18]] = !{[[META19:![0-9]+]]}
+// CHECK-NOFP16: [[META19]] = distinct !{[[META19]], [[META20:![0-9]+]], !"vtrnq_f16: %agg.result"}
+// CHECK-NOFP16: [[META20]] = distinct !{[[META20]], !"vtrnq_f16"}
+//.
+// CHECK-FP16: [[META3]] = !{[[META4:![0-9]+]]}
+// CHECK-FP16: [[META4]] = distinct !{[[META4]], [[META5:![0-9]+]], !"vzip_f16: %agg.result"}
+// CHECK-FP16: [[META5]] = distinct !{[[META5]], !"vzip_f16"}
+// CHECK-FP16: [[META6]] = !{[[META7:![0-9]+]]}
+// CHECK-FP16: [[META7]] = distinct !{[[META7]], [[META8:![0-9]+]], !"vzipq_f16: %agg.result"}
+// CHECK-FP16: [[META8]] = distinct !{[[META8]], !"vzipq_f16"}
+// CHECK-FP16: [[META9]] = !{[[META10:![0-9]+]]}
+// CHECK-FP16: [[META10]] = distinct !{[[META10]], [[META11:![0-9]+]], !"vuzp_f16: %agg.result"}
+// CHECK-FP16: [[META11]] = distinct !{[[META11]], !"vuzp_f16"}
+// CHECK-FP16: [[META12]] = !{[[META13:![0-9]+]]}
+// CHECK-FP16: [[META13]] = distinct !{[[META13]], [[META14:![0-9]+]], !"vuzpq_f16: %agg.result"}
+// CHECK-FP16: [[META14]] = distinct !{[[META14]], !"vuzpq_f16"}
+// CHECK-FP16: [[META15]] = !{[[META16:![0-9]+]]}
+// CHECK-FP16: [[META16]] = distinct !{[[META16]], [[META17:![0-9]+]], !"vtrn_f16: %agg.result"}
+// CHECK-FP16: [[META17]] = distinct !{[[META17]], !"vtrn_f16"}
+// CHECK-FP16: [[META18]] = !{[[META19:![0-9]+]]}
+// CHECK-FP16: [[META19]] = distinct !{[[META19]], [[META20:![0-9]+]], !"vtrnq_f16: %agg.result"}
+// CHECK-FP16: [[META20]] = distinct !{[[META20]], !"vtrnq_f16"}
+//.
diff --git a/clang/test/CodeGen/arm-v8.2a-neon-intrinsics.c b/clang/test/CodeGen/arm-v8.2a-neon-intrinsics.c
index 477da3a..c62d1c9 100644
--- a/clang/test/CodeGen/arm-v8.2a-neon-intrinsics.c
+++ b/clang/test/CodeGen/arm-v8.2a-neon-intrinsics.c
@@ -817,181 +817,3 @@ float16x4_t test_vmul_n_f16(float16x4_t a, float16_t b) {
float16x8_t test_vmulq_n_f16(float16x8_t a, float16_t b) {
return vmulq_n_f16(a, b);
}
-
-// CHECK-LABEL: test_vbsl_f16
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
-// CHECK: [[VBSL:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i8> [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[VBSL]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP3]]
-float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
- return vbsl_f16(a, b, c);
-}
-
-// CHECK-LABEL: test_vbslq_f16
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
-// CHECK: [[VBSL:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[VBSL]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP3]]
-float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
- return vbslq_f16(a, b, c);
-}
-
-// CHECK-LABEL: test_vzip_f16
-// CHECK: [[VZIP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x half> [[VZIP0]], ptr [[addr1:%.*]]
-// CHECK: [[VZIP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x half> [[VZIP1]], ptr [[addr2:%.*]]
-float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
- return vzip_f16(a, b);
-}
-
-// CHECK-LABEL: test_vzipq_f16
-// CHECK: [[VZIP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x half> [[VZIP0]], ptr [[addr1:%.*]]
-// CHECK: [[VZIP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x half> [[VZIP1]], ptr [[addr2:%.*]]
-float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
- return vzipq_f16(a, b);
-}
-
-// CHECK-LABEL: test_vuzp_f16
-// CHECK: [[VUZP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x half> [[VUZP0]], ptr [[addr1:%.*]]
-// CHECK: [[VUZP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x half> [[VUZP1]], ptr [[addr1:%.*]]
-float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
- return vuzp_f16(a, b);
-}
-
-// CHECK-LABEL: test_vuzpq_f16
-// CHECK: [[VUZP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x half> [[VUZP0]], ptr [[addr1:%.*]]
-// CHECK: [[VUZP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x half> [[VUZP1]], ptr [[addr2:%.*]]
-float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
- return vuzpq_f16(a, b);
-}
-
-// CHECK-LABEL: test_vtrn_f16
-// CHECK: [[VTRN0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x half> [[VTRN0]], ptr [[addr1:%.*]]
-// CHECK: [[VTRN1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x half> [[VTRN1]], ptr [[addr2:%.*]]
-float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
- return vtrn_f16(a, b);
-}
-
-// CHECK-LABEL: test_vtrnq_f16
-// CHECK: [[VTRN0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x half> [[VTRN0]], ptr [[addr1:%.*]]
-// CHECK: [[VTRN1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x half> [[VTRN1]], ptr [[addr2:%.*]]
-float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
- return vtrnq_f16(a, b);
-}
-
-// CHECK-LABEL: test_vmov_n_f16
-// CHECK: [[TMP0:%.*]] = insertelement <4 x half> poison, half [[ARG:%.*]], i32 0
-// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
-// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
-// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
-// CHECK: ret <4 x half> [[TMP3]]
-float16x4_t test_vmov_n_f16(float16_t a) {
- return vmov_n_f16(a);
-}
-
-// CHECK-LABEL: test_vmovq_n_f16
-// CHECK: [[TMP0:%.*]] = insertelement <8 x half> poison, half [[ARG:%.*]], i32 0
-// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
-// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
-// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
-// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
-// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
-// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
-// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
-// CHECK: ret <8 x half> [[TMP7]]
-float16x8_t test_vmovq_n_f16(float16_t a) {
- return vmovq_n_f16(a);
-}
-
-// CHECK-LABEL: test_vdup_n_f16
-// CHECK: [[TMP0:%.*]] = insertelement <4 x half> poison, half [[ARG:%.*]], i32 0
-// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
-// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
-// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
-// CHECK: ret <4 x half> [[TMP3]]
-float16x4_t test_vdup_n_f16(float16_t a) {
- return vdup_n_f16(a);
-}
-
-// CHECK-LABEL: test_vdupq_n_f16
-// CHECK: [[TMP0:%.*]] = insertelement <8 x half> poison, half [[ARG:%.*]], i32 0
-// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
-// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
-// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
-// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
-// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
-// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
-// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
-// CHECK: ret <8 x half> [[TMP7]]
-float16x8_t test_vdupq_n_f16(float16_t a) {
- return vdupq_n_f16(a);
-}
-
-// CHECK-LABEL: test_vdup_lane_f16
-// CHECK: [[TMP0:%.*]] = bitcast <4 x half> [[A:%.*]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
-// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
-// CHECK: ret <4 x half> [[LANE]]
-float16x4_t test_vdup_lane_f16(float16x4_t a) {
- return vdup_lane_f16(a, 3);
-}
-
-// CHECK-LABEL: test_vdupq_lane_f16
-// CHECK: [[TMP0:%.*]] = bitcast <4 x half> [[A:%.*]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
-// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
-// CHECK: ret <8 x half> [[LANE]]
-float16x8_t test_vdupq_lane_f16(float16x4_t a) {
- return vdupq_lane_f16(a, 3);
-}
-
-// CHECK-LABEL: @test_vext_f16(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
-// CHECK: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
-// CHECK: ret <4 x half> [[VEXT]]
-float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
- return vext_f16(a, b, 2);
-}
-
-// CHECK-LABEL: @test_vextq_f16(
-// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
-// CHECK: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
-// CHECK: ret <8 x half> [[VEXT]]
-float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
- return vextq_f16(a, b, 5);
-}
-
-// CHECK-LABEL: @test_vrev64_f16(
-// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-// CHECK: ret <4 x half> [[SHFL]]
-float16x4_t test_vrev64_f16(float16x4_t a) {
- return vrev64_f16(a);
-}
-
-// CHECK-LABEL: @test_vrev64q_f16(
-// CHECK: [[SHFL:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
-// CHECK: ret <8 x half> [[SHFL]]
-float16x8_t test_vrev64q_f16(float16x8_t a) {
- return vrev64q_f16(a);
-}
diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c
index 9ec8025..38f9923 100644
--- a/clang/test/CodeGen/cx-complex-range.c
+++ b/clang/test/CodeGen/cx-complex-range.c
@@ -48,6 +48,15 @@
// RUN: -ffast-math -complex-range=promoted -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefix=PRMTD_FAST
+// strict math mode
+// RUN: %clang_cc1 -triple x86_64-windows-pc -complex-range=promoted \
+// RUN: -ffp-contract=off -frounding-math -ffp-exception-behavior=strict \
+// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=X86WINPRMTD_STRICT
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -complex-range=promoted \
+// RUN: -ffp-contract=off -frounding-math -ffp-exception-behavior=strict \
+// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=PRMTD_STRICT
+
// FULL-LABEL: define dso_local <2 x float> @divf(
// FULL-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
// FULL-NEXT: entry:
@@ -504,6 +513,86 @@
// PRMTD_FAST-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
// PRMTD_FAST-NEXT: ret <2 x float> [[TMP11]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local i64 @divf(
+// X86WINPRMTD_STRICT-SAME: i64 noundef [[A_COERCE:%.*]], i64 noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[B:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: store i64 [[A_COERCE]], ptr [[A]], align 4
+// X86WINPRMTD_STRICT-NEXT: store i64 [[B_COERCE]], ptr [[B]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[EXT:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR3:[0-9]+]]
+// X86WINPRMTD_STRICT-NEXT: [[EXT1:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[EXT2:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[B_REAL]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[EXT3:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[B_IMAG]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP0:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT1]], double [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[TMP1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP3:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT2]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT3]], double [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP5:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP3]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP6:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT1]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP7:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP8:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP6]], double [[TMP7]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP9:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP2]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP10:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP8]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP9]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[UNPROMOTION4:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: store float [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[TMP11:%.*]] = load i64, ptr [[RETVAL]], align 4
+// X86WINPRMTD_STRICT-NEXT: ret i64 [[TMP11]]
+//
+// PRMTD_STRICT-LABEL: define dso_local <2 x float> @divf(
+// PRMTD_STRICT-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: [[B:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4
+// PRMTD_STRICT-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[EXT:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR4:[0-9]+]]
+// PRMTD_STRICT-NEXT: [[EXT1:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[EXT2:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[B_REAL]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[EXT3:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[B_IMAG]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT1]], double [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[TMP1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT2]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT3]], double [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP5:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP3]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP6:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT1]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP7:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP8:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP6]], double [[TMP7]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP9:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP2]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP10:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP8]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP9]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[UNPROMOTION4:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4
+// PRMTD_STRICT-NEXT: store float [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
+// PRMTD_STRICT-NEXT: ret <2 x float> [[TMP11]]
+//
_Complex float divf(_Complex float a, _Complex float b) {
return a / b;
}
@@ -873,6 +962,64 @@ _Complex float divf(_Complex float a, _Complex float b) {
// PRMTD_FAST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
// PRMTD_FAST-NEXT: ret <2 x float> [[TMP0]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local i64 @mulf(
+// X86WINPRMTD_STRICT-SAME: i64 noundef [[A_COERCE:%.*]], i64 noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[B:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: store i64 [[A_COERCE]], ptr [[A]], align 4
+// X86WINPRMTD_STRICT-NEXT: store i64 [[B_COERCE]], ptr [[B]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[MUL_AC:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_REAL]], float [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_BD:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_IMAG]], float [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_AD:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_REAL]], float [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_BC:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_IMAG]], float [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[MUL_AC]], float [[MUL_BD]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_I:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[MUL_AD]], float [[MUL_BC]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[TMP0:%.*]] = load i64, ptr [[RETVAL]], align 4
+// X86WINPRMTD_STRICT-NEXT: ret i64 [[TMP0]]
+//
+// PRMTD_STRICT-LABEL: define dso_local <2 x float> @mulf(
+// PRMTD_STRICT-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: [[B:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4
+// PRMTD_STRICT-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[MUL_AC:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_REAL]], float [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_BD:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_IMAG]], float [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_AD:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_REAL]], float [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_BC:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A_IMAG]], float [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[MUL_AC]], float [[MUL_BD]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_I:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[MUL_AD]], float [[MUL_BC]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4
+// PRMTD_STRICT-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
+// PRMTD_STRICT-NEXT: ret <2 x float> [[TMP0]]
+//
_Complex float mulf(_Complex float a, _Complex float b) {
return a * b;
}
@@ -1411,6 +1558,112 @@ _Complex float mulf(_Complex float a, _Complex float b) {
// PRMTD_FAST-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
// PRMTD_FAST-NEXT: ret { double, double } [[TMP15]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local void @divd(
+// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[B_REAL]]) #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[B_IMAG]]) #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[ABS_CMP:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP0]], double [[TMP1]], metadata !"ugt", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
+// X86WINPRMTD_STRICT: abs_rhsr_greater_or_equal_abs_rhsi:
+// X86WINPRMTD_STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[B_IMAG]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP3:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[TMP2]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[B_REAL]], double [[TMP3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP5:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP6:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A_REAL]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP7:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP6]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP8:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP9:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A_IMAG]], double [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP10:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP9]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br label [[COMPLEX_DIV:%.*]]
+// X86WINPRMTD_STRICT: abs_rhsr_less_than_abs_rhsi:
+// X86WINPRMTD_STRICT-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[B_REAL]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[TMP11]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP13:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[B_IMAG]], double [[TMP12]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP14:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP15:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP14]], double [[A_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP16:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP15]], double [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP17:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP18:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP17]], double [[A_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP19:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP18]], double [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br label [[COMPLEX_DIV]]
+// X86WINPRMTD_STRICT: complex_div:
+// X86WINPRMTD_STRICT-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// X86WINPRMTD_STRICT-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[TMP20]], ptr [[AGG_RESULT_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[TMP21]], ptr [[AGG_RESULT_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8
+// X86WINPRMTD_STRICT-NEXT: ret void
+//
+// PRMTD_STRICT-LABEL: define dso_local { double, double } @divd(
+// PRMTD_STRICT-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR2:[0-9]+]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
+// PRMTD_STRICT-NEXT: [[A:%.*]] = alloca { double, double }, align 8
+// PRMTD_STRICT-NEXT: [[B:%.*]] = alloca { double, double }, align 8
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8
+// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8
+// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8
+// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8
+// PRMTD_STRICT-NEXT: [[EXT:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[EXT1:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// PRMTD_STRICT-NEXT: [[EXT2:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[B_REAL]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[EXT3:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[B_IMAG]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[EXT]], x86_fp80 [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP5:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[EXT1]], x86_fp80 [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP6:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[TMP4]], x86_fp80 [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP7:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[EXT2]], x86_fp80 [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP8:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[EXT3]], x86_fp80 [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP9:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[TMP7]], x86_fp80 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP10:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[EXT1]], x86_fp80 [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP11:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[EXT]], x86_fp80 [[EXT3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP12:%.*]] = call x86_fp80 @llvm.experimental.constrained.fsub.f80(x86_fp80 [[TMP10]], x86_fp80 [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP13:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP6]], x86_fp80 [[TMP9]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP14:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP12]], x86_fp80 [[TMP9]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call double @llvm.experimental.constrained.fptrunc.f64.f80(x86_fp80 [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[UNPROMOTION4:%.*]] = call double @llvm.experimental.constrained.fptrunc.f64.f80(x86_fp80 [[TMP14]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store double [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 8
+// PRMTD_STRICT-NEXT: store double [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 8
+// PRMTD_STRICT-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
+// PRMTD_STRICT-NEXT: ret { double, double } [[TMP15]]
+//
_Complex double divd(_Complex double a, _Complex double b) {
return a / b;
}
@@ -1834,6 +2087,78 @@ _Complex double divd(_Complex double a, _Complex double b) {
// PRMTD_FAST-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
// PRMTD_FAST-NEXT: ret { double, double } [[TMP4]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local void @muld(
+// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[MUL_AC:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_BD:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_AD:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_BC:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_R:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[MUL_AC]], double [[MUL_BD]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_I:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[MUL_AD]], double [[MUL_BC]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[MUL_R]], ptr [[AGG_RESULT_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[MUL_I]], ptr [[AGG_RESULT_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8
+// X86WINPRMTD_STRICT-NEXT: ret void
+//
+// PRMTD_STRICT-LABEL: define dso_local { double, double } @muld(
+// PRMTD_STRICT-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR2]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
+// PRMTD_STRICT-NEXT: [[A:%.*]] = alloca { double, double }, align 8
+// PRMTD_STRICT-NEXT: [[B:%.*]] = alloca { double, double }, align 8
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8
+// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8
+// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8
+// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// PRMTD_STRICT-NEXT: [[MUL_AC:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_BD:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_AD:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_BC:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_R:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[MUL_AC]], double [[MUL_BD]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_I:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[MUL_AD]], double [[MUL_BC]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8
+// PRMTD_STRICT-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8
+// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
+// PRMTD_STRICT-NEXT: ret { double, double } [[TMP4]]
+//
_Complex double muld(_Complex double a, _Complex double b) {
return a * b;
}
@@ -2316,6 +2641,114 @@ _Complex double muld(_Complex double a, _Complex double b) {
// PRMTD_FAST-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
// PRMTD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local void @divld(
+// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[B_REAL]]) #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[B_IMAG]]) #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[ABS_CMP:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP0]], double [[TMP1]], metadata !"ugt", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
+// X86WINPRMTD_STRICT: abs_rhsr_greater_or_equal_abs_rhsi:
+// X86WINPRMTD_STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[B_IMAG]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP3:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[TMP2]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[B_REAL]], double [[TMP3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP5:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP6:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A_REAL]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP7:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP6]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP8:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP9:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A_IMAG]], double [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP10:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP9]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br label [[COMPLEX_DIV:%.*]]
+// X86WINPRMTD_STRICT: abs_rhsr_less_than_abs_rhsi:
+// X86WINPRMTD_STRICT-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[B_REAL]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[TMP11]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP13:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[B_IMAG]], double [[TMP12]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP14:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP15:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP14]], double [[A_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP16:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP15]], double [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP17:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP18:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP17]], double [[A_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP19:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP18]], double [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br label [[COMPLEX_DIV]]
+// X86WINPRMTD_STRICT: complex_div:
+// X86WINPRMTD_STRICT-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// X86WINPRMTD_STRICT-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[TMP20]], ptr [[AGG_RESULT_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[TMP21]], ptr [[AGG_RESULT_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8
+// X86WINPRMTD_STRICT-NEXT: ret void
+//
+// PRMTD_STRICT-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld(
+// PRMTD_STRICT-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_REAL]]) #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_IMAG]]) #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[ABS_CMP:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f80(x86_fp80 [[TMP0]], x86_fp80 [[TMP1]], metadata !"ugt", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
+// PRMTD_STRICT: abs_rhsr_greater_or_equal_abs_rhsi:
+// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[B_IMAG]], x86_fp80 [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[TMP2]], x86_fp80 [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[B_REAL]], x86_fp80 [[TMP3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP5:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_IMAG]], x86_fp80 [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP6:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[A_REAL]], x86_fp80 [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP7:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP6]], x86_fp80 [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP8:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_REAL]], x86_fp80 [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP9:%.*]] = call x86_fp80 @llvm.experimental.constrained.fsub.f80(x86_fp80 [[A_IMAG]], x86_fp80 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP10:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP9]], x86_fp80 [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: br label [[COMPLEX_DIV:%.*]]
+// PRMTD_STRICT: abs_rhsr_less_than_abs_rhsi:
+// PRMTD_STRICT-NEXT: [[TMP11:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[B_REAL]], x86_fp80 [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP12:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[TMP11]], x86_fp80 [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP13:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[B_IMAG]], x86_fp80 [[TMP12]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP14:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_REAL]], x86_fp80 [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP15:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[TMP14]], x86_fp80 [[A_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP16:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP15]], x86_fp80 [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP17:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_IMAG]], x86_fp80 [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP18:%.*]] = call x86_fp80 @llvm.experimental.constrained.fsub.f80(x86_fp80 [[TMP17]], x86_fp80 [[A_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP19:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP18]], x86_fp80 [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: br label [[COMPLEX_DIV]]
+// PRMTD_STRICT: complex_div:
+// PRMTD_STRICT-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// PRMTD_STRICT-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store x86_fp80 [[TMP20]], ptr [[RETVAL_REALP]], align 16
+// PRMTD_STRICT-NEXT: store x86_fp80 [[TMP21]], ptr [[RETVAL_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
+// PRMTD_STRICT-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]]
+//
_Complex long double divld(_Complex long double a, _Complex long double b) {
return a / b;
}
@@ -2659,6 +3092,68 @@ _Complex long double divld(_Complex long double a, _Complex long double b) {
// PRMTD_FAST-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
// PRMTD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local void @mulld(
+// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[MUL_AC:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_BD:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_AD:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_REAL]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_BC:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A_IMAG]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_R:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[MUL_AC]], double [[MUL_BD]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[MUL_I:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[MUL_AD]], double [[MUL_BC]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[MUL_R]], ptr [[AGG_RESULT_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[MUL_I]], ptr [[AGG_RESULT_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8
+// X86WINPRMTD_STRICT-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8
+// X86WINPRMTD_STRICT-NEXT: ret void
+//
+// PRMTD_STRICT-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld(
+// PRMTD_STRICT-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[MUL_AC:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_REAL]], x86_fp80 [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_BD:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_IMAG]], x86_fp80 [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_AD:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_REAL]], x86_fp80 [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_BC:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[A_IMAG]], x86_fp80 [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_R:%.*]] = call x86_fp80 @llvm.experimental.constrained.fsub.f80(x86_fp80 [[MUL_AC]], x86_fp80 [[MUL_BD]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[MUL_I:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[MUL_AD]], x86_fp80 [[MUL_BC]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16
+// PRMTD_STRICT-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
+// PRMTD_STRICT-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]]
+//
_Complex long double mulld(_Complex long double a, _Complex long double b) {
return a * b;
}
@@ -3446,6 +3941,167 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) {
// PRMTD_FAST-NEXT: [[TMP33:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
// PRMTD_FAST-NEXT: ret <2 x float> [[TMP33]]
//
+// X86WINPRMTD_STRICT-LABEL: define dso_local i64 @f1(
+// X86WINPRMTD_STRICT-SAME: i64 noundef [[A_COERCE:%.*]], ptr noundef [[B:%.*]], i64 noundef [[C_COERCE:%.*]]) #[[ATTR0]] {
+// X86WINPRMTD_STRICT-NEXT: entry:
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[C:%.*]] = alloca { float, float }, align 4
+// X86WINPRMTD_STRICT-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// X86WINPRMTD_STRICT-NEXT: store i64 [[A_COERCE]], ptr [[A]], align 4
+// X86WINPRMTD_STRICT-NEXT: store i64 [[C_COERCE]], ptr [[C]], align 4
+// X86WINPRMTD_STRICT-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// X86WINPRMTD_STRICT-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[CONV:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[C_REAL]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[CONV1:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[C_IMAG]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[CONV]]) #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[CONV1]]) #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[ABS_CMP:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP0]], double [[TMP1]], metadata !"ugt", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
+// X86WINPRMTD_STRICT: abs_rhsr_greater_or_equal_abs_rhsi:
+// X86WINPRMTD_STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[CONV1]], double [[CONV]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP3:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[TMP2]], double [[CONV1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[CONV]], double [[TMP3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP5:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[B_IMAG]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP6:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[B_REAL]], double [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP7:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP6]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP8:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[B_REAL]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP9:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[B_IMAG]], double [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP10:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP9]], double [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br label [[COMPLEX_DIV:%.*]]
+// X86WINPRMTD_STRICT: abs_rhsr_less_than_abs_rhsi:
+// X86WINPRMTD_STRICT-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[CONV]], double [[CONV1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[TMP11]], double [[CONV]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP13:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[CONV1]], double [[TMP12]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP14:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[B_REAL]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP15:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP14]], double [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP16:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP15]], double [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP17:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[B_IMAG]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP18:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP17]], double [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP19:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP18]], double [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: br label [[COMPLEX_DIV]]
+// X86WINPRMTD_STRICT: complex_div:
+// X86WINPRMTD_STRICT-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// X86WINPRMTD_STRICT-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// X86WINPRMTD_STRICT-NEXT: [[CONV2:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP20]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[CONV3:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP21]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[EXT:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[CONV2]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[EXT4:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[CONV3]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[EXT5:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[EXT6:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP22:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP23:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT4]], double [[EXT6]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP24:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP22]], double [[TMP23]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP25:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT5]], double [[EXT5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP26:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT6]], double [[EXT6]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP25]], double [[TMP26]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT4]], double [[EXT5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT6]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP30:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP28]], double [[TMP29]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP31:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP24]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[TMP32:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP30]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP31]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[UNPROMOTION7:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP32]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]]
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// X86WINPRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// X86WINPRMTD_STRICT-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4
+// X86WINPRMTD_STRICT-NEXT: store float [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 4
+// X86WINPRMTD_STRICT-NEXT: [[TMP33:%.*]] = load i64, ptr [[RETVAL]], align 4
+// X86WINPRMTD_STRICT-NEXT: ret i64 [[TMP33]]
+//
+// PRMTD_STRICT-LABEL: define dso_local <2 x float> @f1(
+// PRMTD_STRICT-SAME: <2 x float> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef [[C_COERCE:%.*]]) #[[ATTR0]] {
+// PRMTD_STRICT-NEXT: entry:
+// PRMTD_STRICT-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: [[C:%.*]] = alloca { float, float }, align 4
+// PRMTD_STRICT-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4
+// PRMTD_STRICT-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4
+// PRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16
+// PRMTD_STRICT-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16
+// PRMTD_STRICT-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4
+// PRMTD_STRICT-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[CONV:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f32(float [[C_REAL]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[CONV1:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f32(float [[C_IMAG]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[ABS_CMP:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f80(x86_fp80 [[TMP0]], x86_fp80 [[TMP1]], metadata !"ugt", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
+// PRMTD_STRICT: abs_rhsr_greater_or_equal_abs_rhsi:
+// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[CONV1]], x86_fp80 [[CONV]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[TMP2]], x86_fp80 [[CONV1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[CONV]], x86_fp80 [[TMP3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP5:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[B_IMAG]], x86_fp80 [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP6:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[B_REAL]], x86_fp80 [[TMP5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP7:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP6]], x86_fp80 [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP8:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[B_REAL]], x86_fp80 [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP9:%.*]] = call x86_fp80 @llvm.experimental.constrained.fsub.f80(x86_fp80 [[B_IMAG]], x86_fp80 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP10:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP9]], x86_fp80 [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: br label [[COMPLEX_DIV:%.*]]
+// PRMTD_STRICT: abs_rhsr_less_than_abs_rhsi:
+// PRMTD_STRICT-NEXT: [[TMP11:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[CONV]], x86_fp80 [[CONV1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP12:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[TMP11]], x86_fp80 [[CONV]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP13:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[CONV1]], x86_fp80 [[TMP12]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP14:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[B_REAL]], x86_fp80 [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP15:%.*]] = call x86_fp80 @llvm.experimental.constrained.fadd.f80(x86_fp80 [[TMP14]], x86_fp80 [[B_IMAG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP16:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP15]], x86_fp80 [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP17:%.*]] = call x86_fp80 @llvm.experimental.constrained.fmul.f80(x86_fp80 [[B_IMAG]], x86_fp80 [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP18:%.*]] = call x86_fp80 @llvm.experimental.constrained.fsub.f80(x86_fp80 [[TMP17]], x86_fp80 [[B_REAL]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP19:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[TMP18]], x86_fp80 [[TMP13]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: br label [[COMPLEX_DIV]]
+// PRMTD_STRICT: complex_div:
+// PRMTD_STRICT-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// PRMTD_STRICT-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
+// PRMTD_STRICT-NEXT: [[CONV2:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f80(x86_fp80 [[TMP20]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[CONV3:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f80(x86_fp80 [[TMP21]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[EXT:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[CONV2]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[EXT4:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[CONV3]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[EXT5:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[EXT6:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP22:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP23:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT4]], double [[EXT6]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP24:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP22]], double [[TMP23]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP25:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT5]], double [[EXT5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP26:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT6]], double [[EXT6]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP25]], double [[TMP26]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT4]], double [[EXT5]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[EXT]], double [[EXT6]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP30:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[TMP28]], double [[TMP29]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP31:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP24]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[TMP32:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[TMP30]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP31]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[UNPROMOTION7:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP32]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR4]]
+// PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// PRMTD_STRICT-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4
+// PRMTD_STRICT-NEXT: store float [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 4
+// PRMTD_STRICT-NEXT: [[TMP33:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
+// PRMTD_STRICT-NEXT: ret <2 x float> [[TMP33]]
+//
_Complex float f1(_Complex float a, _Complex long double b, _Complex float c) {
return (_Complex float)(b / c) / a;
}
+//.
+// FULL: [[PROF2]] = !{!"branch_weights", i32 1, i32 1048575}
+//.
+// FULL_FAST: [[PROF2]] = !{!"branch_weights", i32 1, i32 1048575}
+//.
diff --git a/clang/test/CodeGen/pseudo-probe-emit.c b/clang/test/CodeGen/pseudo-probe-emit.c
index c7a3f7e..360f831e 100644
--- a/clang/test/CodeGen/pseudo-probe-emit.c
+++ b/clang/test/CodeGen/pseudo-probe-emit.c
@@ -10,9 +10,9 @@ void foo(int x) {
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0, i64 -1)
if (x == 0)
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0, i64 -1)
- bar();
+ bar(); // probe id : 3
else
- // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0, i64 -1)
- go();
- // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0, i64 -1)
+ // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0, i64 -1)
+ go(); // probe id : 5
+ // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 6, i32 0, i64 -1)
}
diff --git a/clang/test/CodeGen/remote-traps.c b/clang/test/CodeGen/remote-traps.c
deleted file mode 100644
index 934b76f..0000000
--- a/clang/test/CodeGen/remote-traps.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %clang_cc1 -O1 %s -o - -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -ubsan-exp-hot | FileCheck %s
-// RUN: %clang_cc1 -O1 %s -o - -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -ubsan-exp-hot -mllvm -clang-remove-traps -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --check-prefixes=REMOVE
-
-#include <stdbool.h>
-
-int test(int x) {
- return x + 123;
-}
-
-// CHECK-LABEL: define {{.*}}i32 @test(
-// CHECK: call { i32, i1 } @llvm.sadd.with.overflow.i32(
-// CHECK: trap:
-// CHECK-NEXT: call void @llvm.ubsantrap(i8 0)
-// CHECK-NEXT: unreachable
-
-// REMOVE-LABEL: define {{.*}}i32 @test(
-// REMOVE: add i32 %x, 123
-// REMOVE-NEXT: ret i32
-
-
-bool experimental_hot() __asm("llvm.experimental.hot");
-
-bool test_asm() {
- return experimental_hot();
-}
-
-// CHECK-LABEL: define {{.*}}i1 @test_asm(
-// CHECK: [[R:%.*]] = tail call zeroext i1 @llvm.experimental.hot()
-// CHECK: ret i1 [[R]]
-
-// REMOVE-LABEL: define {{.*}}i1 @test_asm(
-// REMOVE: ret i1 true
diff --git a/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp b/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp
new file mode 100644
index 0000000..80884b4
--- /dev/null
+++ b/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple aarch64_be-apple-darwin -emit-llvm -o - -O1 %s | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-BE %s
+// RUN: %clang_cc1 -triple aarch64-apple-darwin -emit-llvm -o - -O1 %s | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-LE %s
+//
+// Check that TBAA metadata for structs containing bitfields is
+// consistent between big and little endian layouts.
+//
+// FIXME: The metadata below is invalid for the big endian layout: the
+// start offset of 2 is incorrect.
+
+struct NamedBitfields {
+ int f1 : 8;
+ int f2 : 8;
+ unsigned f3 : 1;
+ unsigned f4 : 15;
+ int f5;
+ double f6;
+};
+
+// CHECK-LABEL: _Z4copyP14NamedBitfieldsS0_
+// CHECK-SAME: ptr nocapture noundef writeonly [[A1:%.*]], ptr nocapture noundef readonly [[A2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) [[A1]], ptr noundef nonnull align 8 dereferenceable(16) [[A2]], i64 16, i1 false), !tbaa.struct [[TBAA_STRUCT2:![0-9]+]]
+// CHECK-NEXT: ret void
+//
+void copy(NamedBitfields *a1, NamedBitfields *a2) {
+ *a1 = *a2;
+}
+
+// CHECK-BE: [[TBAA_STRUCT2]] = !{i64 2, i64 4, [[META3:![0-9]+]], i64 4, i64 4, [[META6:![0-9]+]], i64 8, i64 8, [[META8:![0-9]+]]}
+// CHECK-LE: [[TBAA_STRUCT2]] = !{i64 0, i64 4, [[META3:![0-9]+]], i64 4, i64 4, [[META6:![0-9]+]], i64 8, i64 8, [[META8:![0-9]+]]}
+// CHECK: [[META3]] = !{[[META4:![0-9]+]], [[META4]], i64 0}
+// CHECK: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
+// CHECK: [[META5]] = !{!"Simple C++ TBAA"}
+// CHECK: [[META6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
+// CHECK: [[META7]] = !{!"int", [[META4]], i64 0}
+// CHECK: [[META8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
+// CHECK: [[META9]] = !{!"double", [[META4]], i64 0}
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 0000000..dcc2f7f
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,21 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @_Z17empty_record_testiz(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[LIST]])
+// CHECK-NEXT: ret void
+//
+empty empty_record_test(int z, ...) {
+ __builtin_va_list list;
+ __builtin_va_start(list, z);
+ return __builtin_va_arg(list, empty);
+}
diff --git a/clang/test/Driver/mcmodel.c b/clang/test/Driver/mcmodel.c
index 1eb6ae1..9681c32 100644
--- a/clang/test/Driver/mcmodel.c
+++ b/clang/test/Driver/mcmodel.c
@@ -11,6 +11,7 @@
// RUN: FileCheck --check-prefix=AIX-MCMEDIUM-OVERRIDE %s < %t.log
// RUN: not %clang -### -c -mcmodel=lager %s 2>&1 | FileCheck --check-prefix=INVALID %s
// RUN: %clang --target=aarch64 -### -S -mcmodel=large -fno-pic %s 2>&1 | FileCheck --check-prefix=LARGE %s
+// RUN: %clang --target=aarch64-apple-macosx -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=LARGE %s
// RUN: not %clang --target=aarch64 -### -S -mcmodel=large -fpic %s 2>&1 | FileCheck --check-prefix=AARCH64-PIC-LARGE %s
// RUN: not %clang -### -c --target=aarch64 -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=ERR-MEDIUM %s
// RUN: not %clang -### -c --target=aarch64 -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=ERR-KERNEL %s
diff --git a/clang/test/Driver/module-output.cppm b/clang/test/Driver/module-output.cppm
index d0cab0cb..dea9cf9 100644
--- a/clang/test/Driver/module-output.cppm
+++ b/clang/test/Driver/module-output.cppm
@@ -33,6 +33,9 @@
// RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/Hello.pcm -fmodule-output -c -fsyntax-only \
// RUN: -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-NOT-USED
+// Test that we can emit a warning if the type of the input file is not a module interface unit.
+// RUN: %clang -std=c++20 %t/a.cpp -fmodule-output -c -o %t/a.o -### 2>&1 | FileCheck %t/a.cpp
+
//--- Hello.cppm
export module Hello;
@@ -55,3 +58,8 @@ export module AnotherModule;
// CHECK: "-emit-obj" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/Hello-{{.*}}.o" "-x" "pcm" "{{.*}}/Hello.pcm"
// CHECK: "-emit-module-interface" {{.*}}"-main-file-name" "AnotherModule.cppm" {{.*}}"-o" "{{.*}}/AnotherModule.pcm" "-x" "c++" "{{.*}}/AnotherModule.cppm"
// CHECK: "-emit-obj" {{.*}}"-main-file-name" "AnotherModule.cppm" {{.*}}"-o" "{{.*}}/AnotherModule-{{.*}}.o" "-x" "pcm" "{{.*}}/AnotherModule.pcm"
+
+//--- a.cpp
+export module a;
+
+// CHECK: warning: argument unused during compilation: '-fmodule-output'
diff --git a/clang/test/ExtractAPI/anonymous_record_no_typedef.c b/clang/test/ExtractAPI/anonymous_record_no_typedef.c
index 0e50f4a..049e8b1 100644
--- a/clang/test/ExtractAPI/anonymous_record_no_typedef.c
+++ b/clang/test/ExtractAPI/anonymous_record_no_typedef.c
@@ -1,8 +1,9 @@
+// XFAIL: *
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c
index 3c1ef5c..12ac73f 100644
--- a/clang/test/ExtractAPI/availability.c
+++ b/clang/test/ExtractAPI/availability.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
diff --git a/clang/test/ExtractAPI/bool.c b/clang/test/ExtractAPI/bool.c
index f4082ed..efab6df 100644
--- a/clang/test/ExtractAPI/bool.c
+++ b/clang/test/ExtractAPI/bool.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/bool.cpp b/clang/test/ExtractAPI/bool.cpp
index 1b445e2..f7d10c6 100644
--- a/clang/test/ExtractAPI/bool.cpp
+++ b/clang/test/ExtractAPI/bool.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class.cpp b/clang/test/ExtractAPI/class.cpp
index 21cac43..0c5db8e 100644
--- a/clang/test/ExtractAPI/class.cpp
+++ b/clang/test/ExtractAPI/class.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class_template.cpp b/clang/test/ExtractAPI/class_template.cpp
index b04dca6..4f2670d 100644
--- a/clang/test/ExtractAPI/class_template.cpp
+++ b/clang/test/ExtractAPI/class_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
index 0d38fd1..3d7b09f 100644
--- a/clang/test/ExtractAPI/class_template_param_inheritance.cpp
+++ b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class_template_partial_spec.cpp b/clang/test/ExtractAPI/class_template_partial_spec.cpp
index eba0693..c8d9cc7 100644
--- a/clang/test/ExtractAPI/class_template_partial_spec.cpp
+++ b/clang/test/ExtractAPI/class_template_partial_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@@ -15,7 +15,7 @@ template<typename X, typename Y> class Foo {};
template<typename Z> class Foo<Z, int> {};
-/// expected-no-diagnostics
+// expected-no-diagnostics
//--- reference.output.json.in
{
diff --git a/clang/test/ExtractAPI/class_template_spec.cpp b/clang/test/ExtractAPI/class_template_spec.cpp
index 4b183cb..06a9531 100644
--- a/clang/test/ExtractAPI/class_template_spec.cpp
+++ b/clang/test/ExtractAPI/class_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/concept.cpp b/clang/test/ExtractAPI/concept.cpp
index ff4e710..443eac2 100644
--- a/clang/test/ExtractAPI/concept.cpp
+++ b/clang/test/ExtractAPI/concept.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -std=c++20 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/constructor_destructor.cpp b/clang/test/ExtractAPI/constructor_destructor.cpp
index 9742d4b..27112c9 100644
--- a/clang/test/ExtractAPI/constructor_destructor.cpp
+++ b/clang/test/ExtractAPI/constructor_destructor.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@@ -137,7 +137,7 @@ class Foo {
"precise": "c:@S@Foo@F@Foo#"
},
"kind": {
- "displayName": "Instance Method",
+ "displayName": "Constructor",
"identifier": "c++.method"
},
"location": {
@@ -193,7 +193,7 @@ class Foo {
"precise": "c:@S@Foo@F@~Foo#"
},
"kind": {
- "displayName": "Instance Method",
+ "displayName": "Destructor",
"identifier": "c++.method"
},
"location": {
diff --git a/clang/test/ExtractAPI/conversions.cpp b/clang/test/ExtractAPI/conversions.cpp
index fc8d067..07688ff 100644
--- a/clang/test/ExtractAPI/conversions.cpp
+++ b/clang/test/ExtractAPI/conversions.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
index e6b72d5..e668f69 100644
--- a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
+++ b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
@@ -5,18 +5,19 @@
// RUN: %t/reference.main.json.in >> %t/reference.main.json
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.test.json.in >> %t/reference.test.json
-// RUN: %clang_cc1 %t/test.c %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0
+// RUN: %clang_cc1 %t/test.c %t/main.c -emit-symbol-graph --pretty-sgf \
+// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0
// Test main.json
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/SymbolGraphs/main.json > %t/output-normalized.json
+// RUN: %t/SymbolGraphs/main.c.symbols.json > %t/output-normalized.json
// RUN: diff %t/reference.main.json %t/output-normalized.json
// Test test.json
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/SymbolGraphs/test.json > %t/output-normalized.json
+// RUN: %t/SymbolGraphs/test.c.symbols.json > %t/output-normalized.json
// RUN: diff %t/reference.test.json %t/output-normalized.json
// CHECK-NOT: error:
diff --git a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
index 8599e82..b00b5f5 100644
--- a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
+++ b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
@@ -3,11 +3,12 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
+// RUN: %clang_cc1 %t/main.c -emit-symbol-graph --pretty-sgf \
+// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/SymbolGraphs/main.json >> %t/output-normalized.json
+// RUN: %t/SymbolGraphs/main.c.symbols.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
diff --git a/clang/test/ExtractAPI/enum.c b/clang/test/ExtractAPI/enum.c
index 94499d9..1cdf45c 100644
--- a/clang/test/ExtractAPI/enum.c
+++ b/clang/test/ExtractAPI/enum.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/field_template.cpp b/clang/test/ExtractAPI/field_template.cpp
index f05e826..2058ed0 100644
--- a/clang/test/ExtractAPI/field_template.cpp
+++ b/clang/test/ExtractAPI/field_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/function_noexcepts.cpp b/clang/test/ExtractAPI/function_noexcepts.cpp
index 3fc7263..d95eaaa 100644
--- a/clang/test/ExtractAPI/function_noexcepts.cpp
+++ b/clang/test/ExtractAPI/function_noexcepts.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_func_template.cpp b/clang/test/ExtractAPI/global_func_template.cpp
index 8def974..f43a618 100644
--- a/clang/test/ExtractAPI/global_func_template.cpp
+++ b/clang/test/ExtractAPI/global_func_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_func_template_spec.cpp b/clang/test/ExtractAPI/global_func_template_spec.cpp
index a24263d..fe046e9 100644
--- a/clang/test/ExtractAPI/global_func_template_spec.cpp
+++ b/clang/test/ExtractAPI/global_func_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_record.c b/clang/test/ExtractAPI/global_record.c
index 623032b..a08d51d 100644
--- a/clang/test/ExtractAPI/global_record.c
+++ b/clang/test/ExtractAPI/global_record.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_record_multifile.c b/clang/test/ExtractAPI/global_record_multifile.c
index f9d3889..ffdfbcb 100644
--- a/clang/test/ExtractAPI/global_record_multifile.c
+++ b/clang/test/ExtractAPI/global_record_multifile.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input1.h %t/input2.h %t/input3.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_var_template.cpp b/clang/test/ExtractAPI/global_var_template.cpp
index bee2ea6..94f3713 100644
--- a/clang/test/ExtractAPI/global_var_template.cpp
+++ b/clang/test/ExtractAPI/global_var_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
index e98076c..91084f25 100644
--- a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
+++ b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_var_template_spec.cpp b/clang/test/ExtractAPI/global_var_template_spec.cpp
index cca2ab3..ff4d8d1 100644
--- a/clang/test/ExtractAPI/global_var_template_spec.cpp
+++ b/clang/test/ExtractAPI/global_var_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/known_files_only.c b/clang/test/ExtractAPI/known_files_only.c
index 68881aa..de1e786 100644
--- a/clang/test/ExtractAPI/known_files_only.c
+++ b/clang/test/ExtractAPI/known_files_only.c
@@ -1,17 +1,7 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
-// RUN: %t/input1.h -o %t/output.json | FileCheck -allow-empty %s
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
+// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=GlobalRecord -triple arm64-apple-macosx \
+// RUN: %t/input1.h -verify -o - | FileCheck %s
//--- input1.h
int num;
@@ -24,87 +14,6 @@ char not_emitted;
void foo(int);
struct Foo { int a; };
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "GlobalRecord",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "num"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@num"
- },
- "kind": {
- "displayName": "Global Variable",
- "identifier": "c.var"
- },
- "location": {
- "position": {
- "character": 4,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input1.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "num"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "num"
- }
- ],
- "title": "num"
- },
- "pathComponents": [
- "num"
- ]
- }
- ]
-}
+// CHECK-NOT: input2.h
+
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c
index fe98626..90832fd 100644
--- a/clang/test/ExtractAPI/language.c
+++ b/clang/test/ExtractAPI/language.c
@@ -7,11 +7,11 @@
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json
-// RUN: %clang_cc1 -extract-api -x c-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -x c-header -triple arm64-apple-macosx \
// RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s
-// RUN: %clang_cc1 -extract-api -x objective-c-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c-header -triple arm64-apple-macosx \
// RUN: %t/objc.h -o %t/objc.output.json | FileCheck -allow-empty %s
-// RUN: %clang_cc1 -extract-api -x objective-c++-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c++-header -triple arm64-apple-macosx \
// RUN: %t/objcpp.h -o %t/objcpp.output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/macro_undefined.c b/clang/test/ExtractAPI/macro_undefined.c
index 1a4ed20..ec60f95 100644
--- a/clang/test/ExtractAPI/macro_undefined.c
+++ b/clang/test/ExtractAPI/macro_undefined.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/macros.c b/clang/test/ExtractAPI/macros.c
index d5807f6..10003fe 100644
--- a/clang/test/ExtractAPI/macros.c
+++ b/clang/test/ExtractAPI/macros.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/metadata_and_module.c b/clang/test/ExtractAPI/metadata_and_module.c
new file mode 100644
index 0000000..79574a2
--- /dev/null
+++ b/clang/test/ExtractAPI/metadata_and_module.c
@@ -0,0 +1,32 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=module -triple arm64-apple-macosx -x c-header %s -o %t/module.symbols.json -verify
+
+// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix METADATA
+// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix MOD
+
+// expected-no-diagnostics
+
+// METADATA: "metadata": {
+// METADATA-NEXT: "formatVersion": {
+// METADATA-NEXT: "major":
+// METADATA-NEXT: "minor":
+// METADATA-NEXT: "patch":
+// METADATA-NEXT: },
+// METADATA-NEXT: "generator":
+// METADATA-NEXT: }
+
+// MOD: "module": {
+// MOD-NEXT: "name": "module",
+// MOD-NEXT: "platform": {
+// MOD-NEXT: "architecture": "arm64",
+// MOD-NEXT: "operatingSystem": {
+// MOD-NEXT: "minimumVersion": {
+// MOD-NEXT: "major":
+// MOD-NEXT: "minor":
+// MOD-NEXT: "patch":
+// MOD-NEXT: },
+// MOD-NEXT: "name": "macosx"
+// MOD-NEXT: },
+// MOD-NEXT: "vendor": "apple"
+// MOD-NEXT: }
+// MOD-NEXT: }
diff --git a/clang/test/ExtractAPI/method_template.cpp b/clang/test/ExtractAPI/method_template.cpp
index 8d83233..714f9ca 100644
--- a/clang/test/ExtractAPI/method_template.cpp
+++ b/clang/test/ExtractAPI/method_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/method_template_spec.cpp b/clang/test/ExtractAPI/method_template_spec.cpp
index 706d99d..8eaffde 100644
--- a/clang/test/ExtractAPI/method_template_spec.cpp
+++ b/clang/test/ExtractAPI/method_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/methods.cpp b/clang/test/ExtractAPI/methods.cpp
index 8b024a8..412c0bb 100644
--- a/clang/test/ExtractAPI/methods.cpp
+++ b/clang/test/ExtractAPI/methods.cpp
@@ -1,467 +1,221 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
-// RUN: -x c++-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x c++-header %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
class Foo {
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETCOUNT
int getCount();
+ // GETCOUNT: "!testRelLabel": "memberOf $ c:@S@Foo@F@getCount# $ c:@S@Foo"
+ // GETCOUNT-LABEL: "!testLabel": "c:@S@Foo@F@getCount#"
+ // GETCOUNT: "accessLevel": "private",
+ // GETCOUNT: "declarationFragments": [
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "typeIdentifier",
+ // GETCOUNT-NEXT: "preciseIdentifier": "c:I",
+ // GETCOUNT-NEXT: "spelling": "int"
+ // GETCOUNT-NEXT: },
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "text",
+ // GETCOUNT-NEXT: "spelling": " "
+ // GETCOUNT-NEXT: },
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "identifier",
+ // GETCOUNT-NEXT: "spelling": "getCount"
+ // GETCOUNT-NEXT: },
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "text",
+ // GETCOUNT-NEXT: "spelling": "();"
+ // GETCOUNT-NEXT: }
+ // GETCOUNT-NEXT: ],
+ // GETCOUNT: "functionSignature": {
+ // GETCOUNT-NEXT: "returns": [
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "typeIdentifier",
+ // GETCOUNT-NEXT: "preciseIdentifier": "c:I",
+ // GETCOUNT-NEXT: "spelling": "int"
+ // GETCOUNT-NEXT: }
+ // GETCOUNT-NEXT: ]
+ // GETCOUNT-NEXT: },
+ // GETCOUNT: "displayName": "Instance Method",
+ // GETCOUNT-NEXT: "identifier": "c++.method"
+ // GETCOUNT: "title": "getCount"
+ // GETCOUNT: "pathComponents": [
+ // GETCOUNT-NEXT: "Foo",
+ // GETCOUNT-NEXT: "getCount"
+ // GETCOUNT-NEXT: ]
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SETL
void setLength(int length) noexcept;
+ // SETL: "!testRelLabel": "memberOf $ c:@S@Foo@F@setLength#I# $ c:@S@Foo"
+ // SETL-LABEL: "!testLabel": "c:@S@Foo@F@setLength#I#"
+ // SETL: "declarationFragments": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:v",
+ // SETL-NEXT: "spelling": "void"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "identifier",
+ // SETL-NEXT: "spelling": "setLength"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": "("
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:I",
+ // SETL-NEXT: "spelling": "int"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "internalParam",
+ // SETL-NEXT: "spelling": "length"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": ")"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "keyword",
+ // SETL-NEXT: "spelling": "noexcept"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": ";"
+ // SETL-NEXT: }
+ // SETL-NEXT: ],
+ // SETL: "functionSignature": {
+ // SETL-NEXT: "parameters": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "declarationFragments": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:I",
+ // SETL-NEXT: "spelling": "int"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "internalParam",
+ // SETL-NEXT: "spelling": "length"
+ // SETL-NEXT: }
+ // SETL-NEXT: ],
+ // SETL-NEXT: "name": "length"
+ // SETL-NEXT: }
+ // SETL-NEXT: ],
+ // SETL-NEXT: "returns": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:v",
+ // SETL-NEXT: "spelling": "void"
+ // SETL-NEXT: }
+ // SETL-NEXT: ]
+ // SETL-NEXT: },
public:
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETFOO
static double getFoo();
+ // GETFOO: "!testRelLabel": "memberOf $ c:@S@Foo@F@getFoo#S $ c:@S@Foo"
+
+ // GETFOO-LABEL: "!testLabel": "c:@S@Foo@F@getFoo#S"
+ // GETFOO: "accessLevel": "public",
+ // GETFOO: "declarationFragments": [
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "keyword",
+ // GETFOO-NEXT: "spelling": "static"
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "text",
+ // GETFOO-NEXT: "spelling": " "
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "typeIdentifier",
+ // GETFOO-NEXT: "preciseIdentifier": "c:d",
+ // GETFOO-NEXT: "spelling": "double"
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "text",
+ // GETFOO-NEXT: "spelling": " "
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "identifier",
+ // GETFOO-NEXT: "spelling": "getFoo"
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "text",
+ // GETFOO-NEXT: "spelling": "();"
+ // GETFOO-NEXT: }
+ // GETFOO-NEXT: ],
+ // GETFOO: "functionSignature": {
+ // GETFOO-NEXT: "returns": [
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "typeIdentifier",
+ // GETFOO-NEXT: "preciseIdentifier": "c:d",
+ // GETFOO-NEXT: "spelling": "double"
+ // GETFOO-NEXT: }
+ // GETFOO-NEXT: ]
+ // GETFOO-NEXT: },
+ // GETFOO: "kind": {
+ // GETFOO-NEXT: "displayName": "Static Method",
+ // GETFOO-NEXT: "identifier": "c++.type.method"
+ // GETFOO-NEXT: },
protected:
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETBAR
constexpr int getBar() const;
+ // GETBAR: "!testRelLabel": "memberOf $ c:@S@Foo@F@getBar#1 $ c:@S@Foo"
+
+ // GETBAR-LABEL: "!testLabel": "c:@S@Foo@F@getBar#1"
+ // GETBAR: "accessLevel": "protected"
+ // GETBAR: "declarationFragments": [
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "keyword",
+ // GETBAR-NEXT: "spelling": "constexpr"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": " "
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "typeIdentifier",
+ // GETBAR-NEXT: "preciseIdentifier": "c:I",
+ // GETBAR-NEXT: "spelling": "int"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": " "
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "identifier",
+ // GETBAR-NEXT: "spelling": "getBar"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": "() "
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "keyword",
+ // GETBAR-NEXT: "spelling": "const"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": ";"
+ // GETBAR-NEXT: }
+ // GETBAR-NEXT: ],
};
-/// expected-no-diagnostics
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@S@Foo@F@getCount#",
- "target": "c:@S@Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:@S@Foo@F@setLength#I#",
- "target": "c:@S@Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:@S@Foo@F@getBar#1",
- "target": "c:@S@Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:@S@Foo@F@getFoo#S",
- "target": "c:@S@Foo",
- "targetFallback": "Foo"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Foo"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S@Foo"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "c++.class"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "title": "Foo"
- },
- "pathComponents": [
- "Foo"
- ]
- },
- {
- "accessLevel": "private",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "getCount"
- },
- {
- "kind": "text",
- "spelling": "();"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S@Foo@F@getCount#"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getCount"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "getCount"
- }
- ],
- "title": "getCount"
- },
- "pathComponents": [
- "Foo",
- "getCount"
- ]
- },
- {
- "accessLevel": "private",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "setLength"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "length"
- },
- {
- "kind": "text",
- "spelling": ")"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "noexcept"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "length"
- }
- ],
- "name": "length"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S@Foo@F@setLength#I#"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "setLength"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "setLength"
- }
- ],
- "title": "setLength"
- },
- "pathComponents": [
- "Foo",
- "setLength"
- ]
- },
- {
- "accessLevel": "protected",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "constexpr"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "getBar"
- },
- {
- "kind": "text",
- "spelling": "() "
- },
- {
- "kind": "keyword",
- "spelling": "const"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S@Foo@F@getBar#1"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
- },
- "location": {
- "position": {
- "character": 16,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getBar"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "getBar"
- }
- ],
- "title": "getBar"
- },
- "pathComponents": [
- "Foo",
- "getBar"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "static"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:d",
- "spelling": "double"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "getFoo"
- },
- {
- "kind": "text",
- "spelling": "();"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:d",
- "spelling": "double"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S@Foo@F@getFoo#S"
- },
- "kind": {
- "displayName": "Static Method",
- "identifier": "c++.type.method"
- },
- "location": {
- "position": {
- "character": 16,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getFoo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "getFoo"
- }
- ],
- "title": "getFoo"
- },
- "pathComponents": [
- "Foo",
- "getFoo"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/multiple_inheritance.cpp b/clang/test/ExtractAPI/multiple_inheritance.cpp
index a1f069b..7d49cf4 100644
--- a/clang/test/ExtractAPI/multiple_inheritance.cpp
+++ b/clang/test/ExtractAPI/multiple_inheritance.cpp
@@ -3,7 +3,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/namespace.cpp b/clang/test/ExtractAPI/namespace.cpp
index e0c36dd..73e0728 100644
--- a/clang/test/ExtractAPI/namespace.cpp
+++ b/clang/test/ExtractAPI/namespace.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/nested_namespaces.cpp b/clang/test/ExtractAPI/nested_namespaces.cpp
index bd13ef9..c6912cf 100644
--- a/clang/test/ExtractAPI/nested_namespaces.cpp
+++ b/clang/test/ExtractAPI/nested_namespaces.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/objc_block.m b/clang/test/ExtractAPI/objc_block.m
index a7a4f56..4a4335e 100644
--- a/clang/test/ExtractAPI/objc_block.m
+++ b/clang/test/ExtractAPI/objc_block.m
@@ -1,965 +1,630 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -fblocks -triple arm64-apple-macosx \
-// RUN: -x objective-c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -fblocks -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
@interface Foo
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NOPARAM
-(void)methodBlockNoParam:(void (^)())block;
+// NOPARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockNoParam:"
+// NOPARAM: "declarationFragments": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": "- ("
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ") "
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "identifier",
+// NOPARAM-NEXT: "spelling": "methodBlockNoParam:"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": "("
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": " (^"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ")()) "
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "internalParam",
+// NOPARAM-NEXT: "spelling": "block"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ";"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ],
+// NOPARAM: "functionSignature": {
+// NOPARAM-NEXT: "parameters": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "declarationFragments": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": "("
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": " (^"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ")()) "
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "internalParam",
+// NOPARAM-NEXT: "spelling": "block"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ],
+// NOPARAM-NEXT: "name": "block"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ],
+// NOPARAM-NEXT: "returns": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ]
+// NOPARAM-NEXT: }
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PARAM
-(void)methodBlockWithParam:(int (^)(int foo))block;
+// PARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockWithParam:"
+// PARAM: "declarationFragments": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": "- ("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:v",
+// PARAM-NEXT: "spelling": "void"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ") "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "identifier",
+// PARAM-NEXT: "spelling": "methodBlockWithParam:"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": "("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " (^"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "foo"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")) "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "block"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ";"
+// PARAM-NEXT: }
+// PARAM-NEXT: ],
+// PARAM: "functionSignature": {
+// PARAM-NEXT: "parameters": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "declarationFragments": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": "("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " (^"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "foo"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")) "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "block"
+// PARAM-NEXT: }
+// PARAM-NEXT: ],
+// PARAM-NEXT: "name": "block"
+// PARAM-NEXT: }
+// PARAM-NEXT: ],
+// PARAM-NEXT: "returns": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:v",
+// PARAM-NEXT: "spelling": "void"
+// PARAM-NEXT: }
+// PARAM-NEXT: ]
+// PARAM-NEXT: }
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MULTIPARAM
-(void)methodBlockWithMultipleParam:(int (^)(int foo, unsigned baz))block;
+// MULTIPARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:"
+// MULTIPARAM: "declarationFragments": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": "- ("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:v",
+// MULTIPARAM-NEXT: "spelling": "void"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ") "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "identifier",
+// MULTIPARAM-NEXT: "spelling": "methodBlockWithMultipleParam:"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": "("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " (^"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "foo"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ", "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:i",
+// MULTIPARAM-NEXT: "spelling": "unsigned int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "baz"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")) "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "block"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ";"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ],
+// MULTIPARAM: "functionSignature": {
+// MULTIPARAM-NEXT: "parameters": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "declarationFragments": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": "("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " (^"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "foo"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ", "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:i",
+// MULTIPARAM-NEXT: "spelling": "unsigned int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "baz"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")) "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "block"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ],
+// MULTIPARAM-NEXT: "name": "block"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ],
+// MULTIPARAM-NEXT: "returns": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:v",
+// MULTIPARAM-NEXT: "spelling": "void"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ]
+// MULTIPARAM-NEXT: },
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix VARIADIC
-(void)methodBlockVariadic:(int (^)(int foo, ...))block;
+// VARIADIC-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockVariadic:"
+// VARIADIC: "declarationFragments": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": "- ("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:v",
+// VARIADIC-NEXT: "spelling": "void"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ") "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "identifier",
+// VARIADIC-NEXT: "spelling": "methodBlockVariadic:"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": "("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " (^"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ")("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "foo"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ", ...)) "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "block"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ";"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ],
+// VARIADIC: "functionSignature": {
+// VARIADIC-NEXT: "parameters": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "declarationFragments": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": "("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " (^"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ")("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "foo"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ", ...)) "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "block"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ],
+// VARIADIC-NEXT: "name": "block"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ],
+// VARIADIC-NEXT: "returns": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:v",
+// VARIADIC-NEXT: "spelling": "void"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ]
+// VARIADIC-NEXT: },
@end
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FUNC
void func(int (^arg)(int foo));
+// FUNC-LABEL: "!testLabel": "c:@F@func"
+// FUNC: "declarationFragments": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:v",
+// FUNC-NEXT: "spelling": "void"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " "
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "identifier",
+// FUNC-NEXT: "spelling": "func"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": "("
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " (^"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "arg"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": ")("
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " "
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "foo"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": "));"
+// FUNC-NEXT: }
+// FUNC-NEXT: ],
+// FUNC: "functionSignature": {
+// FUNC-NEXT: "parameters": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "declarationFragments": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " (^"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "arg"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": ")("
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " "
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "foo"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": ")"
+// FUNC-NEXT: }
+// FUNC-NEXT: ],
+// FUNC-NEXT: "name": "arg"
+// FUNC-NEXT: }
+// FUNC-NEXT: ],
+// FUNC-NEXT: "returns": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:v",
+// FUNC-NEXT: "spelling": "void"
+// FUNC-NEXT: }
+// FUNC-NEXT: ]
+// FUNC-NEXT: },
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBAL
int (^global)(int foo);
+// GLOBAL-LABEL: "!testLabel": "c:@global"
+// GLOBAL: "declarationFragments": [
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "typeIdentifier",
+// GLOBAL-NEXT: "preciseIdentifier": "c:I",
+// GLOBAL-NEXT: "spelling": "int"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": " (^"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "identifier",
+// GLOBAL-NEXT: "spelling": "global"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": ")("
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "typeIdentifier",
+// GLOBAL-NEXT: "preciseIdentifier": "c:I",
+// GLOBAL-NEXT: "spelling": "int"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": " "
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "internalParam",
+// GLOBAL-NEXT: "spelling": "foo"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": ");"
+// GLOBAL-NEXT: }
+// GLOBAL-NEXT: ],
///expected-no-diagnostics
-
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockNoParam:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockWithParam:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockVariadic:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "identifier",
- "spelling": "global"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ");"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@global"
- },
- "kind": {
- "displayName": "Global Variable",
- "identifier": "objective-c.var"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "global"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "global"
- }
- ],
- "title": "global"
- },
- "pathComponents": [
- "global"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "func"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "internalParam",
- "spelling": "arg"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": "));"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "internalParam",
- "spelling": "arg"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "name": "arg"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@F@func"
- },
- "kind": {
- "displayName": "Function",
- "identifier": "objective-c.func"
- },
- "location": {
- "position": {
- "character": 5,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "func"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "func"
- }
- ],
- "title": "func"
- },
- "pathComponents": [
- "func"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "title": "Foo"
- },
- "pathComponents": [
- "Foo"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockNoParam:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")()) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")()) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockNoParam:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockNoParam:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockNoParam:"
- }
- ],
- "title": "methodBlockNoParam:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockNoParam:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithParam:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockWithParam:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockWithParam:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithParam:"
- }
- ],
- "title": "methodBlockWithParam:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockWithParam:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithMultipleParam:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "baz"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "baz"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockWithMultipleParam:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithMultipleParam:"
- }
- ],
- "title": "methodBlockWithMultipleParam:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockWithMultipleParam:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockVariadic:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", ...)) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", ...)) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockVariadic:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockVariadic:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockVariadic:"
- }
- ],
- "title": "methodBlockVariadic:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockVariadic:"
- ]
- }
- ]
-}
diff --git a/clang/test/ExtractAPI/objc_category.m b/clang/test/ExtractAPI/objc_category.m
index 34b0a9e..9177d40 100644
--- a/clang/test/ExtractAPI/objc_category.m
+++ b/clang/test/ExtractAPI/objc_category.m
@@ -1,341 +1,21 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
-@protocol Protocol;
+@protocol Protocol
+@end
@interface Interface
@end
@interface Interface (Category) <Protocol>
+// CHECK-DAG: "!testRelLabel": "conformsTo $ c:objc(cs)Interface $ c:objc(pl)Protocol"
@property int Property;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)Property $ c:objc(cs)Interface"
- (void)InstanceMethod;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(im)InstanceMethod $ c:objc(cs)Interface"
+ (void)ClassMethod;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cm)ClassMethod $ c:objc(cs)Interface"
@end
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(im)InstanceMethod",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(cm)ClassMethod",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(py)Property",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "conformsTo",
- "source": "c:objc(cs)Interface",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "title": "Interface"
- },
- "pathComponents": [
- "Interface"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "InstanceMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(im)InstanceMethod"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "InstanceMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "InstanceMethod"
- }
- ],
- "title": "InstanceMethod"
- },
- "pathComponents": [
- "Interface",
- "InstanceMethod"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "+ ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "ClassMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(cm)ClassMethod"
- },
- "kind": {
- "displayName": "Type Method",
- "identifier": "objective-c.type.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ClassMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "+ "
- },
- {
- "kind": "identifier",
- "spelling": "ClassMethod"
- }
- ],
- "title": "ClassMethod"
- },
- "pathComponents": [
- "Interface",
- "ClassMethod"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(py)Property"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "title": "Property"
- },
- "pathComponents": [
- "Interface",
- "Property"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_external_category.m b/clang/test/ExtractAPI/objc_external_category.m
new file mode 100644
index 0000000..47e699c
--- /dev/null
+++ b/clang/test/ExtractAPI/objc_external_category.m
@@ -0,0 +1,49 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: --emit-extension-symbol-graphs --symbol-graph-dir=%t/symbols \
+// RUN: --product-name=Module -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules-cache \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %t/input.h -verify
+
+//--- input.h
+#include "ExternalModule.h"
+
+@interface ExtInterface (Category)
+@property int Property;
+- (void)InstanceMethod;
++ (void)ClassMethod;
+@end
+
+@interface ModInterface
+@end
+
+// expected-no-diagnostics
+
+//--- ExternalModule.h
+@interface ExtInterface
+@end
+
+//--- module.modulemap
+module ExternalModule {
+ header "ExternalModule.h"
+}
+
+// RUN: FileCheck %s --input-file %t/symbols/Module.symbols.json --check-prefix MOD
+// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
+// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
+// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(py)Property"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface"
+// MOD-DAG: "!testLabel": "c:objc(cs)ModInterface"
+
+// RUN: FileCheck %s --input-file %t/symbols/ExternalModule@Module.symbols.json --check-prefix EXT
+// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
+// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
+// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
+// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(py)Property"
+// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod"
+// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
+// EXT-NOT: "!testLabel": "c:objc(cs)ExtInterface"
+// EXT-NOT: "!testLabel": "c:objc(cs)ModInterface"
diff --git a/clang/test/ExtractAPI/objc_id_protocol.m b/clang/test/ExtractAPI/objc_id_protocol.m
index 0b0f1b3..f2a03a9 100644
--- a/clang/test/ExtractAPI/objc_id_protocol.m
+++ b/clang/test/ExtractAPI/objc_id_protocol.m
@@ -1,317 +1,56 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o - -verify | FileCheck %s
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
@protocol MyProtocol
@end
@interface MyInterface
@property(copy, readwrite) id<MyProtocol> obj1;
-@property(readwrite) id<MyProtocol> *obj2;
+// CHECK-LABEL: "!testLabel": "c:objc(cs)MyInterface(py)obj1"
+// CHECK: "declarationFragments": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "keyword",
+// CHECK-NEXT: "spelling": "@property"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": " ("
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "keyword",
+// CHECK-NEXT: "spelling": "copy"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": ", "
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "keyword",
+// CHECK-NEXT: "spelling": "readwrite"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": ") "
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "typeIdentifier",
+// CHECK-NEXT: "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
+// CHECK-NEXT: "spelling": "id<MyProtocol>"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": " "
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "identifier",
+// CHECK-NEXT: "spelling": "obj1"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": ";"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
@end
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)MyInterface(py)obj1",
- "target": "c:objc(cs)MyInterface",
- "targetFallback": "MyInterface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)MyInterface(py)obj2",
- "target": "c:objc(cs)MyInterface",
- "targetFallback": "MyInterface"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyInterface"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyInterface"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyInterface"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyInterface"
- }
- ],
- "title": "MyInterface"
- },
- "pathComponents": [
- "MyInterface"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "copy"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "keyword",
- "spelling": "readwrite"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
- "spelling": "id<MyProtocol>"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "obj1"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyInterface(py)obj1"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 42,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "obj1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "obj1"
- }
- ],
- "title": "obj1"
- },
- "pathComponents": [
- "MyInterface",
- "obj1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "readwrite"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
- "spelling": "id<MyProtocol>"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "identifier",
- "spelling": "obj2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyInterface(py)obj2"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 37,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "obj2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "obj2"
- }
- ],
- "title": "obj2"
- },
- "pathComponents": [
- "MyInterface",
- "obj2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@protocol"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyProtocol"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)MyProtocol"
- },
- "kind": {
- "displayName": "Protocol",
- "identifier": "objective-c.protocol"
- },
- "location": {
- "position": {
- "character": 10,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyProtocol"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyProtocol"
- }
- ],
- "title": "MyProtocol"
- },
- "pathComponents": [
- "MyProtocol"
- ]
- }
- ]
-}
+
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_instancetype.m b/clang/test/ExtractAPI/objc_instancetype.m
index d9d259f..071ebe4 100644
--- a/clang/test/ExtractAPI/objc_instancetype.m
+++ b/clang/test/ExtractAPI/objc_instancetype.m
@@ -1,8 +1,8 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
- // RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
+// RUN: %t/reference.output.json.in >> %t/reference.output.json
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
diff --git a/clang/test/ExtractAPI/objc_interface.m b/clang/test/ExtractAPI/objc_interface.m
index ab1772a..4abccdd 100644
--- a/clang/test/ExtractAPI/objc_interface.m
+++ b/clang/test/ExtractAPI/objc_interface.m
@@ -1,701 +1,360 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
-@protocol Protocol;
+@protocol Protocol
+@end
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SUPER
@interface Super <Protocol>
+// SUPER: "!testRelLabel": "conformsTo $ c:objc(cs)Super $ c:objc(pl)Protocol"
+// SUPER-LABEL: "!testLabel": "c:objc(cs)Super"
+// SUPER: "accessLevel": "public",
+// SUPER: "declarationFragments": [
+// SUPER-NEXT: {
+// SUPER-NEXT: "kind": "keyword",
+// SUPER-NEXT: "spelling": "@interface"
+// SUPER-NEXT: },
+// SUPER-NEXT: {
+// SUPER-NEXT: "kind": "text",
+// SUPER-NEXT: "spelling": " "
+// SUPER-NEXT: },
+// SUPER-NEXT: {
+// SUPER-NEXT: "kind": "identifier",
+// SUPER-NEXT: "spelling": "Super"
+// SUPER-NEXT: }
+// SUPER-NEXT: ],
+// SUPER: "kind": {
+// SUPER-NEXT: "displayName": "Class",
+// SUPER-NEXT: "identifier": "objective-c.class"
+// SUPER-NEXT: },
+// SUPER: "title": "Super"
+// SUPER: "pathComponents": [
+// SUPER-NEXT: "Super"
+// SUPER-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PROP
@property(readonly, getter=getProperty) unsigned Property;
+// PROP: "!testRelLabel": "memberOf $ c:objc(cs)Super(py)Property $ c:objc(cs)Super"
+// PROP: "!testLabel": "c:objc(cs)Super(py)Property"
+// PROP: "accessLevel": "public",
+// PROP: "declarationFragments": [
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "keyword",
+// PROP-NEXT: "spelling": "@property"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": " ("
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "keyword",
+// PROP-NEXT: "spelling": "readonly"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": ", "
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "keyword",
+// PROP-NEXT: "spelling": "getter"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": "="
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "identifier",
+// PROP-NEXT: "spelling": "getProperty"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": ") "
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "typeIdentifier",
+// PROP-NEXT: "preciseIdentifier": "c:i",
+// PROP-NEXT: "spelling": "unsigned int"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": " "
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "identifier",
+// PROP-NEXT: "spelling": "Property"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": ";"
+// PROP-NEXT: }
+// PROP-NEXT: ],
+// PROP: "kind": {
+// PROP-NEXT: "displayName": "Instance Property",
+// PROP-NEXT: "identifier": "objective-c.property"
+// PROP-NEXT: },
+// PROP: "title": "Property"
+// PROP: "pathComponents": [
+// PROP-NEXT: "Super",
+// PROP-NEXT: "Property"
+// PROP-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GET
+ (id)getWithProperty:(unsigned) Property;
+// GET: "!testRelLabel": "memberOf $ c:objc(cs)Super(cm)getWithProperty: $ c:objc(cs)Super"
+// GET-LABEL: "!testLabel": "c:objc(cs)Super(cm)getWithProperty:"
+// GET: "accessLevel": "public",
+// GET: "declarationFragments": [
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": "+ ("
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "keyword",
+// GET-NEXT: "spelling": "id"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ") "
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "identifier",
+// GET-NEXT: "spelling": "getWithProperty:"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": "("
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "typeIdentifier",
+// GET-NEXT: "preciseIdentifier": "c:i",
+// GET-NEXT: "spelling": "unsigned int"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ") "
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "internalParam",
+// GET-NEXT: "spelling": "Property"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ";"
+// GET-NEXT: }
+// GET-NEXT: ],
+// GET: "functionSignature": {
+// GET-NEXT: "parameters": [
+// GET-NEXT: {
+// GET-NEXT: "declarationFragments": [
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": "("
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "typeIdentifier",
+// GET-NEXT: "preciseIdentifier": "c:i",
+// GET-NEXT: "spelling": "unsigned int"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ") "
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "internalParam",
+// GET-NEXT: "spelling": "Property"
+// GET-NEXT: }
+// GET-NEXT: ],
+// GET-NEXT: "name": "Property"
+// GET-NEXT: }
+// GET-NEXT: ],
+// GET-NEXT: "returns": [
+// GET-NEXT: {
+// GET-NEXT: "kind": "keyword",
+// GET-NEXT: "spelling": "id"
+// GET-NEXT: }
+// GET-NEXT: ]
+// GET-NEXT: },
+// GET: "kind": {
+// GET-NEXT: "displayName": "Type Method",
+// GET-NEXT: "identifier": "objective-c.type.method"
+// GET-NEXT: },
+// GET: "title": "getWithProperty:"
+// GET: "pathComponents": [
+// GET-NEXT: "Super",
+// GET-NEXT: "getWithProperty:"
+// GET-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SET
- (void)setProperty:(unsigned) Property andOtherThing: (unsigned) Thing;
+// SET: "!testRelLabel": "memberOf $ c:objc(cs)Super(im)setProperty:andOtherThing: $ c:objc(cs)Super"
+// SET-LABEL: "!testLabel": "c:objc(cs)Super(im)setProperty:andOtherThing:"
+// SET: "accessLevel": "public",
+// SET: "declarationFragments": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "- ("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:v",
+// SET-NEXT: "spelling": "void"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "identifier",
+// SET-NEXT: "spelling": "setProperty:"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Property"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": " "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "identifier",
+// SET-NEXT: "spelling": "andOtherThing:"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Thing"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ";"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET: "functionSignature": {
+// SET-NEXT: "parameters": [
+// SET-NEXT: {
+// SET-NEXT: "declarationFragments": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Property"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET-NEXT: "name": "Property"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "declarationFragments": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Thing"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET-NEXT: "name": "Thing"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET-NEXT: "returns": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:v",
+// SET-NEXT: "spelling": "void"
+// SET-NEXT: }
+// SET-NEXT: ]
+// SET-NEXT: },
+// SET: "kind": {
+// SET-NEXT: "displayName": "Instance Method",
+// SET-NEXT: "identifier": "objective-c.method"
+// SET-NEXT: },
+// SET: "title": "setProperty:andOtherThing:"
@end
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix DERIVED
@interface Derived : Super {
+// DERIVED: "!testRelLabel": "inheritsFrom $ c:objc(cs)Derived $ c:objc(cs)Super"
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix IVAR
char Ivar;
+// IVAR: "!testRelLabel": "memberOf $ c:objc(cs)Derived@Ivar $ c:objc(cs)Derived"
+// IVAR-LABEL: "!testLabel": "c:objc(cs)Derived@Ivar"
+// IVAR: "accessLevel": "public",
+// IVAR: "declarationFragments": [
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "typeIdentifier",
+// IVAR-NEXT: "preciseIdentifier": "c:C",
+// IVAR-NEXT: "spelling": "char"
+// IVAR-NEXT: },
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "text",
+// IVAR-NEXT: "spelling": " "
+// IVAR-NEXT: },
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "identifier",
+// IVAR-NEXT: "spelling": "Ivar"
+// IVAR-NEXT: },
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "text",
+// IVAR-NEXT: "spelling": ";"
+// IVAR-NEXT: }
+// IVAR-NEXT: ],
+// IVAR: "kind": {
+// IVAR-NEXT: "displayName": "Instance Variable",
+// IVAR-NEXT: "identifier": "objective-c.ivar"
+// IVAR-NEXT: },
+// IVAR: "title": "Ivar"
+// IVAR: "pathComponents": [
+// IVAR-NEXT: "Derived",
+// IVAR-NEXT: "Ivar"
+// IVAR-NEXT: ]
}
-- (char)getIvar;
@end
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Super(cm)getWithProperty:",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Super(im)setProperty:andOtherThing:",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Super(py)Property",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- },
- {
- "kind": "conformsTo",
- "source": "c:objc(cs)Super",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Derived@Ivar",
- "target": "c:objc(cs)Derived",
- "targetFallback": "Derived"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Derived(im)getIvar",
- "target": "c:objc(cs)Derived",
- "targetFallback": "Derived"
- },
- {
- "kind": "inheritsFrom",
- "source": "c:objc(cs)Derived",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Super"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Super"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Super"
- }
- ],
- "title": "Super"
- },
- "pathComponents": [
- "Super"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "+ ("
- },
- {
- "kind": "keyword",
- "spelling": "id"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "getWithProperty:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- }
- ],
- "name": "Property"
- }
- ],
- "returns": [
- {
- "kind": "keyword",
- "spelling": "id"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super(cm)getWithProperty:"
- },
- "kind": {
- "displayName": "Type Method",
- "identifier": "objective-c.type.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getWithProperty:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "+ "
- },
- {
- "kind": "identifier",
- "spelling": "getWithProperty:"
- }
- ],
- "title": "getWithProperty:"
- },
- "pathComponents": [
- "Super",
- "getWithProperty:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "setProperty:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "andOtherThing:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Thing"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- }
- ],
- "name": "Property"
- },
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Thing"
- }
- ],
- "name": "Thing"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super(im)setProperty:andOtherThing:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "setProperty:andOtherThing:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "setProperty:andOtherThing:"
- }
- ],
- "title": "setProperty:andOtherThing:"
- },
- "pathComponents": [
- "Super",
- "setProperty:andOtherThing:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "readonly"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "keyword",
- "spelling": "getter"
- },
- {
- "kind": "text",
- "spelling": "="
- },
- {
- "kind": "identifier",
- "spelling": "getProperty"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super(py)Property"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 49,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "title": "Property"
- },
- "pathComponents": [
- "Super",
- "Property"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Derived"
- },
- {
- "kind": "text",
- "spelling": " : "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)Super",
- "spelling": "Super"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Derived"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Derived"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Derived"
- }
- ],
- "title": "Derived"
- },
- "pathComponents": [
- "Derived"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:C",
- "spelling": "char"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Ivar"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Derived@Ivar"
- },
- "kind": {
- "displayName": "Instance Variable",
- "identifier": "objective-c.ivar"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Ivar"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Ivar"
- }
- ],
- "title": "Ivar"
- },
- "pathComponents": [
- "Derived",
- "Ivar"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:C",
- "spelling": "char"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "getIvar"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:C",
- "spelling": "char"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Derived(im)getIvar"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getIvar"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "getIvar"
- }
- ],
- "title": "getIvar"
- },
- "pathComponents": [
- "Derived",
- "getIvar"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_module_category.m b/clang/test/ExtractAPI/objc_module_category.m
deleted file mode 100644
index 708ed10..0000000
--- a/clang/test/ExtractAPI/objc_module_category.m
+++ /dev/null
@@ -1,404 +0,0 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header \
-// RUN: -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
-#import "Foundation.h"
-
-/// Doc comment 1
-@interface NSString (Category1)
--(void)method1;
-@end
-
-/// Doc comment 2
-@interface NSString (Category2)
--(void)method2;
-@end
-
-//--- Foundation.h
-@interface NSString
-@end
-
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString@Category1",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)method1",
- "target": "c:objc(cy)NSString@Category1",
- "targetFallback": "Category1"
- },
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString@Category2",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)method2",
- "target": "c:objc(cy)NSString@Category2",
- "targetFallback": "Category2"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString@Category1"
- },
- "kind": {
- "displayName": "Module Extension",
- "identifier": "objective-c.module.extension"
- }
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category1"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "docComment": {
- "lines": [
- {
- "range": {
- "end": {
- "character": 17,
- "line": 2
- },
- "start": {
- "character": 4,
- "line": 2
- }
- },
- "text": "Doc comment 1"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString@Category1"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "title": "NSString (Category1)"
- },
- "pathComponents": [
- "Category1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "method1"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)method1"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "method1"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "method1"
- }
- ],
- "title": "method1"
- },
- "pathComponents": [
- "Category1",
- "method1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category2"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "docComment": {
- "lines": [
- {
- "range": {
- "end": {
- "character": 17,
- "line": 7
- },
- "start": {
- "character": 4,
- "line": 7
- }
- },
- "text": "Doc comment 2"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString@Category2"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "title": "NSString (Category2)"
- },
- "pathComponents": [
- "Category2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "method2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)method2"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "method2"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "method2"
- }
- ],
- "title": "method2"
- },
- "pathComponents": [
- "Category2",
- "method2"
- ]
- }
- ]
-}
diff --git a/clang/test/ExtractAPI/objc_property.m b/clang/test/ExtractAPI/objc_property.m
index 5712abc..f05584c 100644
--- a/clang/test/ExtractAPI/objc_property.m
+++ b/clang/test/ExtractAPI/objc_property.m
@@ -1,608 +1,26 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
@protocol Protocol
@property(class) int myProtocolTypeProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(cpy)myProtocolTypeProp $ c:objc(pl)Protocol"
@property int myProtocolInstanceProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(py)myProtocolInstanceProp $ c:objc(pl)Protocol"
@end
@interface Interface
@property(class) int myInterfaceTypeProp;
+// CHECk-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myInterfaceTypeProp $ c:objc(cs)Interface"
@property int myInterfaceInstanceProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myInterfaceInstanceProp $ c:objc(cs)Interface"
@end
@interface Interface (Category) <Protocol>
@property(class) int myCategoryTypeProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myCategoryTypeProp $ c:objc(cs)Interface"
@property int myCategoryInstanceProp;
+// CHECK-DAG "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myCategoryInstanceProp $ c:objc(cs)Interface"
@end
-// expected-no-diagnostics
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(cpy)myInterfaceTypeProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(py)myInterfaceInstanceProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(cpy)myCategoryTypeProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(py)myCategoryInstanceProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "conformsTo",
- "source": "c:objc(cs)Interface",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(pl)Protocol(cpy)myProtocolTypeProp",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(pl)Protocol(py)myProtocolInstanceProp",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "title": "Interface"
- },
- "pathComponents": [
- "Interface"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myInterfaceTypeProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(cpy)myInterfaceTypeProp"
- },
- "kind": {
- "displayName": "Type Property",
- "identifier": "objective-c.type.property"
- },
- "location": {
- "position": {
- "character": 21,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceTypeProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceTypeProp"
- }
- ],
- "title": "myInterfaceTypeProp"
- },
- "pathComponents": [
- "Interface",
- "myInterfaceTypeProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myInterfaceInstanceProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(py)myInterfaceInstanceProp"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceInstanceProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceInstanceProp"
- }
- ],
- "title": "myInterfaceInstanceProp"
- },
- "pathComponents": [
- "Interface",
- "myInterfaceInstanceProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myCategoryTypeProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(cpy)myCategoryTypeProp"
- },
- "kind": {
- "displayName": "Type Property",
- "identifier": "objective-c.type.property"
- },
- "location": {
- "position": {
- "character": 21,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myCategoryTypeProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myCategoryTypeProp"
- }
- ],
- "title": "myCategoryTypeProp"
- },
- "pathComponents": [
- "Interface",
- "myCategoryTypeProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myCategoryInstanceProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(py)myCategoryInstanceProp"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 12
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myCategoryInstanceProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myCategoryInstanceProp"
- }
- ],
- "title": "myCategoryInstanceProp"
- },
- "pathComponents": [
- "Interface",
- "myCategoryInstanceProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@protocol"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Protocol"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)Protocol"
- },
- "kind": {
- "displayName": "Protocol",
- "identifier": "objective-c.protocol"
- },
- "location": {
- "position": {
- "character": 10,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Protocol"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Protocol"
- }
- ],
- "title": "Protocol"
- },
- "pathComponents": [
- "Protocol"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myProtocolTypeProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)Protocol(cpy)myProtocolTypeProp"
- },
- "kind": {
- "displayName": "Type Property",
- "identifier": "objective-c.type.property"
- },
- "location": {
- "position": {
- "character": 21,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myProtocolTypeProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myProtocolTypeProp"
- }
- ],
- "title": "myProtocolTypeProp"
- },
- "pathComponents": [
- "Protocol",
- "myProtocolTypeProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myProtocolInstanceProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)Protocol(py)myProtocolInstanceProp"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myProtocolInstanceProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myProtocolInstanceProp"
- }
- ],
- "title": "myProtocolInstanceProp"
- },
- "pathComponents": [
- "Protocol",
- "myProtocolInstanceProp"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_protocol.m b/clang/test/ExtractAPI/objc_protocol.m
index a04936f..06f7ee3 100644
--- a/clang/test/ExtractAPI/objc_protocol.m
+++ b/clang/test/ExtractAPI/objc_protocol.m
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf -x objective-c-header -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/objc_various_categories.m b/clang/test/ExtractAPI/objc_various_categories.m
deleted file mode 100644
index adaef5a..0000000
--- a/clang/test/ExtractAPI/objc_various_categories.m
+++ /dev/null
@@ -1,507 +0,0 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header \
-// RUN: -target arm64-apple-macosx \
-// RUN: %t/myclass_1.h \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
-#import "myclass_1.h"
-#import "Foundation.h"
-
-@interface MyClass1 (MyCategory1)
-- (int) SomeMethod;
-@end
-
-@interface NSString (Category1)
--(void) StringMethod;
-@end
-
-@interface NSString (Category2)
--(void) StringMethod2;
-@end
-
-//--- myclass_1.h
-@interface MyClass1
-@end
-
-//--- Foundation.h
-@interface NSString
-@end
-
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)MyClass1(im)SomeMethod",
- "target": "c:objc(cs)MyClass1",
- "targetFallback": "MyClass1"
- },
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString@Category1",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)StringMethod",
- "target": "c:objc(cy)NSString@Category1",
- "targetFallback": "Category1"
- },
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString@Category2",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)StringMethod2",
- "target": "c:objc(cy)NSString@Category2",
- "targetFallback": "Category2"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyClass1"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyClass1"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 0
- },
- "uri": "file://INPUT_DIR/myclass_1.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyClass1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyClass1"
- }
- ],
- "title": "MyClass1"
- },
- "pathComponents": [
- "MyClass1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "SomeMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyClass1(im)SomeMethod"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "SomeMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "SomeMethod"
- }
- ],
- "title": "SomeMethod"
- },
- "pathComponents": [
- "MyClass1",
- "SomeMethod"
- ]
- },
- {
- "accessLevel": "public",
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString@Category1"
- },
- "kind": {
- "displayName": "Module Extension",
- "identifier": "objective-c.module.extension"
- }
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category1"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString@Category1"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "title": "NSString (Category1)"
- },
- "pathComponents": [
- "Category1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)StringMethod"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "StringMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod"
- }
- ],
- "title": "StringMethod"
- },
- "pathComponents": [
- "Category1",
- "StringMethod"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category2"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString@Category2"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "title": "NSString (Category2)"
- },
- "pathComponents": [
- "Category2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)StringMethod2"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 12
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "StringMethod2"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod2"
- }
- ],
- "title": "StringMethod2"
- },
- "pathComponents": [
- "Category2",
- "StringMethod2"
- ]
- }
- ]
-}
diff --git a/clang/test/ExtractAPI/operator_overload.cpp b/clang/test/ExtractAPI/operator_overload.cpp
index 511a5a7..9430c58 100644
--- a/clang/test/ExtractAPI/operator_overload.cpp
+++ b/clang/test/ExtractAPI/operator_overload.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/relative_include.m b/clang/test/ExtractAPI/relative_include.m
index 46cbdaee..e5a0268 100644
--- a/clang/test/ExtractAPI/relative_include.m
+++ b/clang/test/ExtractAPI/relative_include.m
@@ -15,7 +15,7 @@
// RUN: %hmaptool write %t/headermap.hmap.json %t/headermap.hmap
// Input headers use paths to the framework root/DSTROOT
-// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \
// RUN: -triple arm64-apple-macosx \
// RUN: -iquote%t -I%t/headermap.hmap -F%t/Frameworks \
// RUN: -x objective-c-header \
diff --git a/clang/test/ExtractAPI/simple_inheritance.cpp b/clang/test/ExtractAPI/simple_inheritance.cpp
index 5fe99af..58c3c4e 100644
--- a/clang/test/ExtractAPI/simple_inheritance.cpp
+++ b/clang/test/ExtractAPI/simple_inheritance.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/struct.c b/clang/test/ExtractAPI/struct.c
index 4284b73..1995a6ae 100644
--- a/clang/test/ExtractAPI/struct.c
+++ b/clang/test/ExtractAPI/struct.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/typedef.c b/clang/test/ExtractAPI/typedef.c
index c30e655..a4c3619 100644
--- a/clang/test/ExtractAPI/typedef.c
+++ b/clang/test/ExtractAPI/typedef.c
@@ -1,391 +1,93 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=Typedef -target arm64-apple-macosx \
-// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MYINT
typedef int MyInt;
+// MYINT-LABEL: "!testLabel": "c:typedef.c@T@MyInt"
+// MYINT: "accessLevel": "public",
+// MYINT: "declarationFragments": [
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "keyword",
+// MYINT-NEXT: "spelling": "typedef"
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "text",
+// MYINT-NEXT: "spelling": " "
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "typeIdentifier",
+// MYINT-NEXT: "preciseIdentifier": "c:I",
+// MYINT-NEXT: "spelling": "int"
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "text",
+// MYINT-NEXT: "spelling": " "
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "identifier",
+// MYINT-NEXT: "spelling": "MyInt"
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "text",
+// MYINT-NEXT: "spelling": ";"
+// MYINT-NEXT: }
+// MYINT-NEXT: ],
+// MYINT: "kind": {
+// MYINT-NEXT: "displayName": "Type Alias",
+// MYINT-NEXT: "identifier": "objective-c.typealias"
+// MYINT-NEXT: },
+// MYINT: "title": "MyInt"
+// MYINT: "pathComponents": [
+// MYINT-NEXT: "MyInt"
+// MYINT-NEXT: ],
+// MYINT: "type": "c:I"
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BARPTR
typedef struct Bar *BarPtr;
+// BARPTR-LABEL: "!testLabel": "c:typedef.c@T@BarPtr"
+// BARPTR: "accessLevel": "public",
+// BARPTR: "declarationFragments": [
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "keyword",
+// BARPTR-NEXT: "spelling": "typedef"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": " "
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "keyword",
+// BARPTR-NEXT: "spelling": "struct"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": " "
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "typeIdentifier",
+// BARPTR-NEXT: "preciseIdentifier": "c:@S@Bar",
+// BARPTR-NEXT: "spelling": "Bar"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": " * "
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "identifier",
+// BARPTR-NEXT: "spelling": "BarPtr"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": ";"
+// BARPTR-NEXT: }
+// BARPTR-NEXT: ],
+// BARPTR: "type": "c:*$@S@Bar"
+// RUN: FileCheck %s --input-file %t/output.symbols.json
void foo(BarPtr value);
void baz(BarPtr *value);
+// CHECK-NOT: struct Bar *
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "Typedef",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h@T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- },
- {
- "kind": "text",
- "spelling": ");"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h@T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- }
- ],
- "name": "value"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@F@foo"
- },
- "kind": {
- "displayName": "Function",
- "identifier": "objective-c.func"
- },
- "location": {
- "position": {
- "character": 5,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "foo"
- }
- ],
- "title": "foo"
- },
- "pathComponents": [
- "foo"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "baz"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h@T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- },
- {
- "kind": "text",
- "spelling": ");"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h@T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- }
- ],
- "name": "value"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@F@baz"
- },
- "kind": {
- "displayName": "Function",
- "identifier": "objective-c.func"
- },
- "location": {
- "position": {
- "character": 5,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "baz"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "baz"
- }
- ],
- "title": "baz"
- },
- "pathComponents": [
- "baz"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyInt"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:input.h@T@MyInt"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "objective-c.typealias"
- },
- "location": {
- "position": {
- "character": 12,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyInt"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyInt"
- }
- ],
- "title": "MyInt"
- },
- "pathComponents": [
- "MyInt"
- ],
- "type": "c:I"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@S@Bar",
- "spelling": "Bar"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "identifier",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:input.h@T@BarPtr"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "objective-c.typealias"
- },
- "location": {
- "position": {
- "character": 20,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "BarPtr"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "BarPtr"
- }
- ],
- "title": "BarPtr"
- },
- "pathComponents": [
- "BarPtr"
- ],
- "type": "c:*$@S@Bar"
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/typedef_anonymous_record.c b/clang/test/ExtractAPI/typedef_anonymous_record.c
index 3e4c3e1..9e00ff7 100644
--- a/clang/test/ExtractAPI/typedef_anonymous_record.c
+++ b/clang/test/ExtractAPI/typedef_anonymous_record.c
@@ -1,468 +1,158 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --product-name=TypedefChain -triple arm64-apple-macosx \
-// RUN: -x c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c-header %s -o %t/typedefchain.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCT
typedef struct { } MyStruct;
+// MYSTRUCT-LABEL: "!testLabel": "c:@SA@MyStruct"
+// MYSTRUCT: "accessLevel": "public",
+// MYSTRUCT: "declarationFragments": [
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "keyword",
+// MYSTRUCT-NEXT: "spelling": "typedef"
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "text",
+// MYSTRUCT-NEXT: "spelling": " "
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "keyword",
+// MYSTRUCT-NEXT: "spelling": "struct"
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "text",
+// MYSTRUCT-NEXT: "spelling": " "
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "identifier",
+// MYSTRUCT-NEXT: "spelling": "MyStruct"
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "text",
+// MYSTRUCT-NEXT: "spelling": ";"
+// MYSTRUCT-NEXT: }
+// MYSTRUCT-NEXT: ]
+// MYSTRUCT: "kind": {
+// MYSTRUCT-NEXT: "displayName": "Structure",
+// MYSTRUCT-NEXT: "identifier": "c.struct"
+// MYSTRUCT: "title": "MyStruct"
+// MYSTRUCT: "pathComponents": [
+// MYSTRUCT-NEXT: "MyStruct"
+// MYSTRUCT-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCTSTRUCT
typedef MyStruct MyStructStruct;
-typedef MyStructStruct MyStructStructStruct;
+// MYSTRUCTSTRUCT-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyStructStruct"
+// MYSTRUCTSTRUCT: "accessLevel": "public",
+// MYSTRUCTSTRUCT: "declarationFragments": [
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "keyword",
+// MYSTRUCTSTRUCT-NEXT: "spelling": "typedef"
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "text",
+// MYSTRUCTSTRUCT-NEXT: "spelling": " "
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "typeIdentifier",
+// MYSTRUCTSTRUCT-NEXT: "preciseIdentifier": "c:@SA@MyStruct",
+// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStruct"
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "text",
+// MYSTRUCTSTRUCT-NEXT: "spelling": " "
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "identifier",
+// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStructStruct"
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "text",
+// MYSTRUCTSTRUCT-NEXT: "spelling": ";"
+// MYSTRUCTSTRUCT-NEXT: }
+// MYSTRUCTSTRUCT-NEXT:],
+// MYSTRUCTSTRUCT: "kind": {
+// MYSTRUCTSTRUCT-NEXT: "displayName": "Type Alias",
+// MYSTRUCTSTRUCT-NEXT: "identifier": "c.typealias"
+
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUM
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix CASE
typedef enum { Case } MyEnum;
+// MYENUM: "source": "c:@EA@MyEnum@Case",
+// MYENUM-NEXT: "target": "c:@EA@MyEnum",
+// MYENUM-NEXT: "targetFallback": "MyEnum"
+// MYENUM-LABEL: "!testLabel": "c:@EA@MyEnum"
+// MYENUM: "declarationFragments": [
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "keyword",
+// MYENUM-NEXT: "spelling": "typedef"
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "text",
+// MYENUM-NEXT: "spelling": " "
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "keyword",
+// MYENUM-NEXT: "spelling": "enum"
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "text",
+// MYENUM-NEXT: "spelling": " "
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "identifier",
+// MYENUM-NEXT: "spelling": "MyEnum"
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "text",
+// MYENUM-NEXT: "spelling": ";"
+// MYENUM-NEXT: }
+// MYENUM-NEXT:],
+// MYENUM: "kind": {
+// MYENUM-NEXT: "displayName": "Enumeration",
+// MYENUM-NEXT: "identifier": "c.enum"
+// MYENUM: "title": "MyEnum"
+
+// CASE-LABEL: "!testLabel": "c:@EA@MyEnum@Case"
+// CASE: "pathComponents": [
+// CASE-NEXT: "MyEnum",
+// CASE-NEXT: "Case"
+// CASE-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUMENUM
typedef MyEnum MyEnumEnum;
-typedef MyEnumEnum MyEnumEnumEnum;
-// expected-no-diagnostics
+// MYENUMENUM-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyEnumEnum"
+// MYENUMENUM: "declarationFragments": [
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "keyword",
+// MYENUMENUM-NEXT: "spelling": "typedef"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "text",
+// MYENUMENUM-NEXT: "spelling": " "
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "typeIdentifier",
+// MYENUMENUM-NEXT: "preciseIdentifier": "c:@EA@MyEnum",
+// MYENUMENUM-NEXT: "spelling": "MyEnum"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "text",
+// MYENUMENUM-NEXT: "spelling": " "
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "identifier",
+// MYENUMENUM-NEXT: "spelling": "MyEnumEnum"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "text",
+// MYENUMENUM-NEXT: "spelling": ";"
+// MYENUMENUM-NEXT: }
+// MYENUMENUM-NEXT: ],
+// MYENUMENUM: "kind": {
+// MYENUMENUM-NEXT: "displayName": "Type Alias",
+// MYENUMENUM-NEXT: "identifier": "c.typealias"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM: "title": "MyEnumEnum"
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "TypedefChain",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@EA@MyEnum@Case",
- "target": "c:@EA@MyEnum",
- "targetFallback": "MyEnum"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "enum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyEnum"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@EA@MyEnum"
- },
- "kind": {
- "displayName": "Enumeration",
- "identifier": "c.enum"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyEnum"
- }
- ],
- "title": "MyEnum"
- },
- "pathComponents": [
- "MyEnum"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "identifier",
- "spelling": "Case"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@EA@MyEnum@Case"
- },
- "kind": {
- "displayName": "Enumeration Case",
- "identifier": "c.enum.case"
- },
- "location": {
- "position": {
- "character": 15,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Case"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Case"
- }
- ],
- "title": "Case"
- },
- "pathComponents": [
- "MyEnum",
- "Case"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyStruct"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@SA@MyStruct"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyStruct"
- }
- ],
- "title": "MyStruct"
- },
- "pathComponents": [
- "MyStruct"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@SA@MyStruct",
- "spelling": "MyStruct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyStructStruct"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@MyStructStruct"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 17,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyStructStruct"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyStructStruct"
- }
- ],
- "title": "MyStructStruct"
- },
- "pathComponents": [
- "MyStructStruct"
- ],
- "type": "c:@SA@MyStruct"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h@T@MyStructStruct",
- "spelling": "MyStructStruct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyStructStructStruct"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@MyStructStructStruct"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 23,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyStructStructStruct"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyStructStructStruct"
- }
- ],
- "title": "MyStructStructStruct"
- },
- "pathComponents": [
- "MyStructStructStruct"
- ],
- "type": "c:input.h@T@MyStructStruct"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@EA@MyEnum",
- "spelling": "MyEnum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyEnumEnum"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@MyEnumEnum"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 15,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnum"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnum"
- }
- ],
- "title": "MyEnumEnum"
- },
- "pathComponents": [
- "MyEnumEnum"
- ],
- "type": "c:@EA@MyEnum"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h@T@MyEnumEnum",
- "spelling": "MyEnumEnum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyEnumEnumEnum"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@MyEnumEnumEnum"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 19,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnumEnum"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnumEnum"
- }
- ],
- "title": "MyEnumEnumEnum"
- },
- "pathComponents": [
- "MyEnumEnumEnum"
- ],
- "type": "c:input.h@T@MyEnumEnum"
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/typedef_chain.c b/clang/test/ExtractAPI/typedef_chain.c
index 9e6151c..05d4eb5 100644
--- a/clang/test/ExtractAPI/typedef_chain.c
+++ b/clang/test/ExtractAPI/typedef_chain.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=TypedefChain -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=TypedefChain -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/typedef_struct_enum.c b/clang/test/ExtractAPI/typedef_struct_enum.c
index 15357d5..fb6fbe9 100644
--- a/clang/test/ExtractAPI/typedef_struct_enum.c
+++ b/clang/test/ExtractAPI/typedef_struct_enum.c
@@ -1,445 +1,146 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -x c-header %s -triple arm64-apple-macos -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST
typedef struct Test {
} Test;
+// TEST-LABEL: "!testLabel": "c:@S@Test"
+// TEST: "declarationFragments": [
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "keyword",
+// TEST-NEXT: "spelling": "typedef"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": " "
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "keyword",
+// TEST-NEXT: "spelling": "struct"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": " "
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "identifier",
+// TEST-NEXT: "spelling": "Test"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": " { ... } "
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "identifier",
+// TEST-NEXT: "spelling": "Test"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": ";"
+// TEST-NEXT: }
+// TEST-NEXT: ],
+// TEST: "displayName": "Structure",
+// TEST: "title": "Test"
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST2
typedef enum Test2 {
simple
} Test2;
+// TEST2-LABEL: "!testLabel": "c:@E@Test2"
+// TEST2: "declarationFragments": [
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "keyword",
+// TEST2-NEXT: "spelling": "typedef"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": " "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "keyword",
+// TEST2-NEXT: "spelling": "enum"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": " "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "identifier",
+// TEST2-NEXT: "spelling": "Test2"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": ": "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "typeIdentifier",
+// TEST2-NEXT: "preciseIdentifier": "c:i",
+// TEST2-NEXT: "spelling": "unsigned int"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": " { ... } "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "identifier",
+// TEST2-NEXT: "spelling": "Test2"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": ";"
+// TEST2-NEXT: }
+// TEST2-NEXT: ],
+// TEST2: "displayName": "Enumeration",
+// TEST2: "title": "Test2"
+
struct Foo;
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPEDEF
typedef struct Foo TypedefedFoo;
+// TYPEDEF-LABEL: "!testLabel": "c:typedef_struct_enum.c@T@TypedefedFoo"
+// TYPEDEF: "declarationFragments": [
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "keyword",
+// TYPEDEF-NEXT: "spelling": "typedef"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": " "
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "keyword",
+// TYPEDEF-NEXT: "spelling": "struct"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": " "
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "typeIdentifier",
+// TYPEDEF-NEXT: "preciseIdentifier": "c:@S@Foo",
+// TYPEDEF-NEXT: "spelling": "Foo"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": " "
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "identifier",
+// TYPEDEF-NEXT: "spelling": "TypedefedFoo"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": ";"
+// TYPEDEF-NEXT: }
+// TYPEDEF-NEXT: ],
+// TYPEDEF: "displayName": "Type Alias",
+// TYPEDEF: "title": "TypedefedFoo"
+// TYPEDEF: "type": "c:@S@Foo"
+
struct Foo {
int bar;
};
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@E@Test2@simple",
- "target": "c:@E@Test2",
- "targetFallback": "Test2"
- },
- {
- "kind": "memberOf",
- "source": "c:@S@Foo@FI@bar",
- "target": "c:@S@Foo",
- "targetFallback": "Foo"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "enum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Test2"
- },
- {
- "kind": "text",
- "spelling": ": "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " { ... } "
- },
- {
- "kind": "identifier",
- "spelling": "Test2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@E@Test2"
- },
- "kind": {
- "displayName": "Enumeration",
- "identifier": "c.enum"
- },
- "location": {
- "position": {
- "character": 13,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Test2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Test2"
- }
- ],
- "title": "Test2"
- },
- "pathComponents": [
- "Test2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "identifier",
- "spelling": "simple"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@E@Test2@simple"
- },
- "kind": {
- "displayName": "Enumeration Case",
- "identifier": "c.enum.case"
- },
- "location": {
- "position": {
- "character": 2,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "simple"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "simple"
- }
- ],
- "title": "simple"
- },
- "pathComponents": [
- "Test2",
- "simple"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Test"
- },
- {
- "kind": "text",
- "spelling": " { ... } "
- },
- {
- "kind": "identifier",
- "spelling": "Test"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S@Test"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 15,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Test"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Test"
- }
- ],
- "title": "Test"
- },
- "pathComponents": [
- "Test"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Foo"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S@Foo"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "title": "Foo"
- },
- "pathComponents": [
- "Foo"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "bar"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S@Foo@FI@bar"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "c.property"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 10
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "bar"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "bar"
- }
- ],
- "title": "bar"
- },
- "pathComponents": [
- "Foo",
- "bar"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@S@Foo",
- "spelling": "Foo"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "TypedefedFoo"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@TypedefedFoo"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 19,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "TypedefedFoo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "TypedefedFoo"
- }
- ],
- "title": "TypedefedFoo"
- },
- "pathComponents": [
- "TypedefedFoo"
- ],
- "type": "c:@S@Foo"
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/underscored.c b/clang/test/ExtractAPI/underscored.c
index 30d2b63..204ec36 100644
--- a/clang/test/ExtractAPI/underscored.c
+++ b/clang/test/ExtractAPI/underscored.c
@@ -1,17 +1,5 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
-// RUN: -x c-header %t/input.h -o %t/output.json -verify
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
-// expected-no-diagnostics
+// RUN: -x c-header %s -o - -verify | FileCheck %s
// Global record
int _HiddenGlobal;
@@ -19,399 +7,22 @@ int exposed_global;
// Record type
struct _HiddenRecord {
- int a;
+ int HiddenRecordMember;
};
struct ExposedRecord {
- int a;
+ int ExposedRecordMember;
};
-// Typedef
-typedef struct {} _HiddenTypedef;
-typedef int ExposedTypedef;
-typedef _HiddenTypedef ExposedTypedefToHidden;
-
// Macros
#define _HIDDEN_MACRO 5
#define EXPOSED_MACRO 5
-// Symbols that start with '_' should not appear in the reference output
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@S@ExposedRecord@FI@a",
- "target": "c:@S@ExposedRecord",
- "targetFallback": "ExposedRecord"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "exposed_global"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@exposed_global"
- },
- "kind": {
- "displayName": "Global Variable",
- "identifier": "c.var"
- },
- "location": {
- "position": {
- "character": 4,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "exposed_global"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "exposed_global"
- }
- ],
- "title": "exposed_global"
- },
- "pathComponents": [
- "exposed_global"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "ExposedRecord"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S@ExposedRecord"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ExposedRecord"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "ExposedRecord"
- }
- ],
- "title": "ExposedRecord"
- },
- "pathComponents": [
- "ExposedRecord"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "a"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S@ExposedRecord@FI@a"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "c.property"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 12
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "a"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "a"
- }
- ],
- "title": "a"
- },
- "pathComponents": [
- "ExposedRecord",
- "a"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "#define"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "EXPOSED_MACRO"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@335@macro@EXPOSED_MACRO"
- },
- "kind": {
- "displayName": "Macro",
- "identifier": "c.macro"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 22
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "EXPOSED_MACRO"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "EXPOSED_MACRO"
- }
- ],
- "title": "EXPOSED_MACRO"
- },
- "pathComponents": [
- "EXPOSED_MACRO"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "ExposedTypedef"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@ExposedTypedef"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 12,
- "line": 17
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedef"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedef"
- }
- ],
- "title": "ExposedTypedef"
- },
- "pathComponents": [
- "ExposedTypedef"
- ],
- "type": "c:I"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@SA@_HiddenTypedef",
- "spelling": "_HiddenTypedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "ExposedTypedefToHidden"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h@T@ExposedTypedefToHidden"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 23,
- "line": 18
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedefToHidden"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedefToHidden"
- }
- ],
- "title": "ExposedTypedefToHidden"
- },
- "pathComponents": [
- "ExposedTypedefToHidden"
- ],
- "type": "c:@SA@_HiddenTypedef"
- }
- ]
-}
+// expected-no-diagnostics
+
+// CHECK-NOT: _HiddenRecord
+// CHECK-NOT: HiddenRecordMember
+// CHECK: ExposedRecord
+// CHECK: ExposedRecordMember
+// CHECK-NOT: _HIDDEN_MACRO
+// CHECK: EXPOSED_MACRO
diff --git a/clang/test/ExtractAPI/union.c b/clang/test/ExtractAPI/union.c
index 6ec9fd3..8f8300b 100644
--- a/clang/test/ExtractAPI/union.c
+++ b/clang/test/ExtractAPI/union.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x c-header\
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x c-header\
// RUN: %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@@ -12,7 +12,7 @@
//--- input.h
/// My Union
-union Union{
+union Union {
/// the a option
int a;
/// the b option
diff --git a/clang/test/ExtractAPI/vfs_redirected_include.m b/clang/test/ExtractAPI/vfs_redirected_include.m
index 9ba7e1d..db03820 100644
--- a/clang/test/ExtractAPI/vfs_redirected_include.m
+++ b/clang/test/ExtractAPI/vfs_redirected_include.m
@@ -14,7 +14,7 @@
// RUN: %t/vfsoverlay.yaml.in >> %t/vfsoverlay.yaml
// Input headers use paths to the framework root/DSTROOT
-// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \
// RUN: -triple arm64-apple-macosx \
// RUN: -iquote%t -ivfsoverlay %t/vfsoverlay.yaml -F%t/Frameworks \
// RUN: -x objective-c-header \
diff --git a/clang/test/Index/extract-api-cursor.m b/clang/test/Index/extract-api-cursor.m
index 1b27b6f..9d9d3a1 100644
--- a/clang/test/Index/extract-api-cursor.m
+++ b/clang/test/Index/extract-api-cursor.m
@@ -31,6 +31,8 @@ struct Foo {
- (void)derivedMethodWithValue:(id<Protocol>)value {
int a = 5;
}
+/// Impl only docs
+- (void)implOnlyMethod { }
@end
// RUN: c-index-test -single-symbol-sgf-at=%s:4:9 local %s | FileCheck -check-prefix=CHECK-FOO %s
@@ -118,3 +120,10 @@ struct Foo {
// CHECK-DERIVED-METHOD-IMPL: "text":"Derived method docs"
// CHECK-DERIVED-METHOD-IMPL: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-DERIVED-METHOD-IMPL: "title":"derivedMethodWithValue:"
+
+// RUN: c-index-test -single-symbol-sgf-at=%s:35:11 local %s | FileCheck -check-prefix=CHECK-IMPL-ONLY %s
+// CHECK-IMPL-ONLY: "relatedSymbols":[]
+// CHECK-IMPL-ONLY: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)implOnlyMethod","target":"c:objc(cs)Derived"
+// CHECK-IMPL-ONLY: "text":"Impl only docs"
+// CHECK-IMPL-ONLY: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
+// CHECK-IMPL-ONLY: "title":"implOnlyMethod"
diff --git a/clang/test/InstallAPI/driver-invalid-options.test b/clang/test/InstallAPI/driver-invalid-options.test
index 69f3b2d..0c630ea 100644
--- a/clang/test/InstallAPI/driver-invalid-options.test
+++ b/clang/test/InstallAPI/driver-invalid-options.test
@@ -7,3 +7,9 @@
// RUN: not clang-installapi -target x86_64-apple-ios-simulator %s -o tmp.tbd 2> %t
// RUN: FileCheck --check-prefix INVALID_INSTALL_NAME -input-file %t %s
// INVALID_INSTALL_NAME: error: no install name specified: add -install_name <path>
+
+/// Check invalid verification mode.
+// RUN: not clang-installapi -install_name Foo -target arm64-apple-ios13 \
+// RUN: --verify-mode=Invalid -o tmp.tbd 2> %t
+// RUN: FileCheck --check-prefix INVALID_VERIFY_MODE -input-file %t %s
+// INVALID_VERIFY_MODE: error: invalid value 'Invalid' in '--verify-mode=Invalid'
diff --git a/clang/test/Interpreter/inline-asm.cpp b/clang/test/Interpreter/inline-asm.cpp
new file mode 100644
index 0000000..f94f14d
--- /dev/null
+++ b/clang/test/Interpreter/inline-asm.cpp
@@ -0,0 +1,17 @@
+// REQUIRES: host-supports-jit, x86_64-linux
+// UNSUPPORTED: system-aix
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: cat %t/inline-asm.txt | clang-repl -Xcc="-I%t"
+
+//--- inline-asm.cpp
+__asm(".globl _ZSt21ios_base_library_initv");
+int x;
+
+//--- inline-asm.txt
+#include "inline-asm.cpp"
+x = 10;
+%quit
diff --git a/clang/test/Modules/reduced-bmi-size.cppm b/clang/test/Modules/reduced-bmi-size.cppm
new file mode 100644
index 0000000..664f45f
--- /dev/null
+++ b/clang/test/Modules/reduced-bmi-size.cppm
@@ -0,0 +1,16 @@
+// Ensure that the size of the reduced BMI is not larger than the full BMI
+// in the most simple case.
+
+// This test requires linux commands.
+// REQUIRES: system-linux
+
+// RUN: rm -fr %t
+// RUN: mkdir %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %s -o %t/a.reduced.pcm
+//
+// %s implies the current source file. So we can't use it directly.
+// RUN: [ $(stat -c%\s "%t/a.pcm") -le $(stat -c%\s "%t/a.reduced.pcm") ]
+
+export module a;
diff --git a/clang/test/Parser/c2x-typeof-ext-warns.c b/clang/test/Parser/c2x-typeof-ext-warns.c
index 3871844..7a1f673 100644
--- a/clang/test/Parser/c2x-typeof-ext-warns.c
+++ b/clang/test/Parser/c2x-typeof-ext-warns.c
@@ -12,9 +12,12 @@
// standards before C23, and Clang has followed suit. Neither compiler exposes
// 'typeof_unqual' as a non-conforming extension.
-// Show what happens with the underscored version of the keyword, which is a
-// conforming extension.
+// Show what happens with the underscored version of the keywords, which are
+// conforming extensions.
__typeof__(int) i = 12;
+__typeof(int) _i = 12;
+__typeof_unqual__(int) u = 12;
+__typeof_unqual(int) _u = 12;
// Show what happens with a regular 'typeof' use.
typeof(i) j = 12; // c11-error {{expected function body after function declarator}} \
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index d494d5e..f01f513 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -62,6 +62,17 @@ void foo1(int A)
[[clang::code_align(64)]] // expected-error{{conflicting loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
+ [[clang::code_align(4)]] // expected-note{{previous attribute is here}}
+ [[clang::code_align(4)]] // OK
+ [[clang::code_align(8)]] // expected-error{{conflicting loop attribute 'code_align'}}
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ [[clang::code_align(4)]] // expected-note 2{{previous attribute is here}}
+ [[clang::code_align(4)]] // OK
+ [[clang::code_align(8)]] // expected-error{{conflicting loop attribute 'code_align'}}
+ [[clang::code_align(64)]] // expected-error{{conflicting loop attribute 'code_align'}}
+ for(int I=0; I<128; ++I) { bar(I); }
+
// expected-error@+1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 7}}
[[clang::code_align(7)]]
for(int I=0; I<128; ++I) { bar(I); }
@@ -135,6 +146,17 @@ void code_align_dependent() {
[[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
+ [[clang::code_align(A)]] // cpp-local-note{{previous attribute is here}}
+ [[clang::code_align(A)]] // OK
+ [[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}}
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ [[clang::code_align(A)]] // cpp-local-note 2{{previous attribute is here}}
+ [[clang::code_align(A)]] // OK
+ [[clang::code_align(C)]] // cpp-local-error{{conflicting loop attribute 'code_align'}}
+ [[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}}
+ for(int I=0; I<128; ++I) { bar(I); }
+
// cpp-local-error@+1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 23}}
[[clang::code_align(B)]]
for(int I=0; I<128; ++I) { bar(I); }
diff --git a/clang/test/SemaCXX/typeof_unqual.cpp b/clang/test/SemaCXX/typeof_unqual.cpp
new file mode 100644
index 0000000..335e579
--- /dev/null
+++ b/clang/test/SemaCXX/typeof_unqual.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typeof_unqual(int) u = 12; // expected-error {{expected function body after function declarator}}
+__typeof_unqual(int) _u = 12;
+__typeof_unqual__(int) __u = 12;
diff --git a/clang/test/SemaCXX/warn-unused-but-set-variables-cpp.cpp b/clang/test/SemaCXX/warn-unused-but-set-variables-cpp.cpp
index 418baa7..eaedb53 100644
--- a/clang/test/SemaCXX/warn-unused-but-set-variables-cpp.cpp
+++ b/clang/test/SemaCXX/warn-unused-but-set-variables-cpp.cpp
@@ -69,3 +69,11 @@ template <typename T> void f5() {
SWarnUnused swu;
++swu;
}
+
+void f6() {
+ if (int x = 123) {} // expected-warning{{variable 'x' set but not used}}
+
+ while (int x = 123) {} // expected-warning{{variable 'x' set but not used}}
+
+ for (; int x = 123;) {} // expected-warning{{variable 'x' set but not used}}
+}
diff --git a/clang/test/SemaHLSL/ArrayTemporary.ll b/clang/test/SemaHLSL/ArrayTemporary.ll
deleted file mode 100644
index 5eec009..0000000
--- a/clang/test/SemaHLSL/ArrayTemporary.ll
+++ /dev/null
@@ -1,76 +0,0 @@
-; ModuleID = '/Users/cbieneman/dev/llvm-project/clang/test/SemaHLSL/ArrayTemporary.hlsl'
-source_filename = "/Users/cbieneman/dev/llvm-project/clang/test/SemaHLSL/ArrayTemporary.hlsl"
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
-target triple = "dxil-pc-shadermodel6.3-library"
-
-%struct.Obj = type { float, i32 }
-
-@"__const.?call3@@YAXXZ.Arr" = private unnamed_addr constant [2 x [2 x float]] [[2 x float] zeroinitializer, [2 x float] [float 1.000000e+00, float 1.000000e+00]], align 4
-
-; Function Attrs: noinline nounwind optnone
-define void @"?fn@@YAXY01M@Z"(ptr noundef byval([2 x float]) align 4 %x) #0 {
-entry:
- ret void
-}
-
-; Function Attrs: noinline nounwind optnone
-define void @"?call@@YAXXZ"() #0 {
-entry:
- %Arr = alloca [2 x float], align 4
- %agg.tmp = alloca [2 x float], align 4
- call void @llvm.memset.p0.i32(ptr align 4 %Arr, i8 0, i32 8, i1 false)
- call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.tmp, ptr align 4 %Arr, i32 8, i1 false)
- call void @"?fn@@YAXY01M@Z"(ptr noundef byval([2 x float]) align 4 %agg.tmp)
- ret void
-}
-
-; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
-declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #1
-
-; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
-declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2
-
-; Function Attrs: noinline nounwind optnone
-define void @"?fn2@@YAXY03UObj@@@Z"(ptr noundef byval([4 x %struct.Obj]) align 4 %O) #0 {
-entry:
- ret void
-}
-
-; Function Attrs: noinline nounwind optnone
-define void @"?call2@@YAXXZ"() #0 {
-entry:
- %Arr = alloca [4 x %struct.Obj], align 4
- %agg.tmp = alloca [4 x %struct.Obj], align 4
- call void @llvm.memset.p0.i32(ptr align 4 %Arr, i8 0, i32 32, i1 false)
- call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.tmp, ptr align 4 %Arr, i32 32, i1 false)
- call void @"?fn2@@YAXY03UObj@@@Z"(ptr noundef byval([4 x %struct.Obj]) align 4 %agg.tmp)
- ret void
-}
-
-; Function Attrs: noinline nounwind optnone
-define void @"?fn3@@YAXY111M@Z"(ptr noundef byval([2 x [2 x float]]) align 4 %x) #0 {
-entry:
- ret void
-}
-
-; Function Attrs: noinline nounwind optnone
-define void @"?call3@@YAXXZ"() #0 {
-entry:
- %Arr = alloca [2 x [2 x float]], align 4
- %agg.tmp = alloca [2 x [2 x float]], align 4
- call void @llvm.memcpy.p0.p0.i32(ptr align 4 %Arr, ptr align 4 @"__const.?call3@@YAXXZ.Arr", i32 16, i1 false)
- call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.tmp, ptr align 4 %Arr, i32 16, i1 false)
- call void @"?fn3@@YAXY111M@Z"(ptr noundef byval([2 x [2 x float]]) align 4 %agg.tmp)
- ret void
-}
-
-attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }
-attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
-
-!llvm.module.flags = !{!0, !1}
-!llvm.ident = !{!2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
-!2 = !{!"clang version 19.0.0git (git@github.com:llvm/llvm-project.git 64e1c15c520cf11114ef2ddd887e76560903db2b)"}
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 5bad814..aecf61b 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -152,6 +152,7 @@ int main(int argc, const char **argv) {
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
if (OptHostSupportsJit) {
auto J = llvm::orc::LLJITBuilder().create();
diff --git a/clang/tools/libclang/CXExtractAPI.cpp b/clang/tools/libclang/CXExtractAPI.cpp
index 05098c9..d74f374 100644
--- a/clang/tools/libclang/CXExtractAPI.cpp
+++ b/clang/tools/libclang/CXExtractAPI.cpp
@@ -18,6 +18,7 @@
#include "clang-c/Index.h"
#include "clang-c/Platform.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/ExtractAPI/API.h"
@@ -54,41 +55,20 @@ struct LibClangExtractAPIVisitor
if (!shouldDeclBeIncluded(Decl))
return true;
- const ObjCInterfaceDecl *Interface = Decl->getClassInterface();
- StringRef Name = Interface->getName();
- StringRef USR = API.recordUSR(Decl);
- PresumedLoc Loc =
- Context.getSourceManager().getPresumedLoc(Decl->getLocation());
- LinkageInfo Linkage = Decl->getLinkageAndVisibility();
- DocComment Comment;
- if (auto *RawComment = fetchRawCommentForDecl(Interface))
- Comment = RawComment->getFormattedLines(Context.getSourceManager(),
- Context.getDiagnostics());
-
- // Build declaration fragments and sub-heading by generating them for the
- // interface.
- DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Interface);
- DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(Decl);
-
- // Collect super class information.
- SymbolReference SuperClass;
- if (const auto *SuperClassDecl = Decl->getSuperClass()) {
- SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
- SuperClass.USR = API.recordUSR(SuperClassDecl);
- }
+ auto *Interface = Decl->getClassInterface();
- ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment, Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
+ if (!VisitObjCInterfaceDecl(Interface))
+ return false;
- // Record all methods (selectors). This doesn't include automatically
- // synthesized property methods.
- recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
- recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
- recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
+ SmallString<128> USR;
+ index::generateUSRForDecl(Interface, USR);
+ if (auto *InterfaceRecord = dyn_cast_if_present<ObjCInterfaceRecord>(
+ API.findRecordForUSR(USR))) {
+ recordObjCMethods(InterfaceRecord, Decl->methods());
+ recordObjCProperties(InterfaceRecord, Decl->properties());
+ recordObjCInstanceVariables(InterfaceRecord, Decl->ivars());
+ }
return true;
}
};
@@ -96,21 +76,14 @@ struct LibClangExtractAPIVisitor
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet)
-static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
- Decl *D);
-
-template <typename DeclTy>
-static bool WalkupParentContext(DeclContext *Parent,
- LibClangExtractAPIVisitor &Visitor) {
- if (auto *D = dyn_cast<DeclTy>(Parent)) {
- WalkupFromMostDerivedType(Visitor, D);
- return true;
- }
- return false;
-}
-
+// Visits the Decl D and it's transitive DeclContexts recursively, starting from
+// the outer-most context. This is guaranteed to visit every Decl we need in the
+// right order to generate symbol graph information for D.
static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
Decl *D) {
+ if (auto *Parent = D->getDeclContext())
+ WalkupFromMostDerivedType(Visitor, cast<Decl>(Parent));
+
switch (D->getKind()) {
#define ABSTRACT_DECL(DECL)
#define DECL(CLASS, BASE) \
@@ -119,20 +92,12 @@ static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
break;
#include "clang/AST/DeclNodes.inc"
}
-
- for (auto *Parent = D->getDeclContext(); Parent != nullptr;
- Parent = Parent->getParent()) {
- if (WalkupParentContext<ObjCContainerDecl>(Parent, Visitor))
- return;
- if (WalkupParentContext<TagDecl>(Parent, Visitor))
- return;
- }
}
static CXString GenerateCXStringFromSymbolGraphData(llvm::json::Object Obj) {
llvm::SmallString<0> BackingString;
llvm::raw_svector_ostream OS(BackingString);
- OS << Value(std::move(Obj));
+ OS << llvm::formatv("{0}", Value(std::move(Obj)));
return cxstring::createDup(BackingString.str());
}
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 35ab7e3..acc596f 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5317,6 +5317,34 @@ TEST_P(ASTImporterOptionSpecificTestBase,
EXPECT_FALSE(ToX);
}
+TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclInlineWithCXX17) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct S {
+ template <unsigned> static constexpr bool X = true;
+ };
+ )",
+ Lang_CXX17, "input1.cc");
+ Decl *FromTU2 = getTuDecl(
+ R"(
+ struct S {
+ template <unsigned> static constexpr bool X = true;
+ template <typename T> void get() { X<sizeof(T)>; }
+ };
+ template <typename U> U qvariant_cast(const S &v) { return v.get; }
+ )",
+ Lang_CXX17, "input2.cc");
+ auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
+ FromTU, varTemplateDecl(hasName("X")));
+ auto *ToX = Import(FromX, Lang_CXX17);
+ ASSERT_TRUE(ToX);
+ auto *FromX2 = FirstDeclMatcher<VarTemplateDecl>().match(
+ FromTU2, varTemplateDecl(hasName("X")));
+ auto *ToX2 = Import(FromX2, Lang_CXX17);
+ EXPECT_TRUE(ToX2);
+ EXPECT_EQ(ToX, ToX2);
+}
+
TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {
constexpr auto Code =
R"(
diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
index bea00ab..b0b579d 100644
--- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -805,6 +805,25 @@ public:
else
JoinedVal.setProperty("is_null", JoinedEnv.makeTopBoolValue());
}
+
+ std::optional<WidenResult> widen(QualType Type, Value &Prev,
+ const Environment &PrevEnv, Value &Current,
+ Environment &CurrentEnv) override {
+ switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) {
+ case ComparisonResult::Same:
+ return WidenResult{&Current, LatticeJoinEffect::Unchanged};
+ case ComparisonResult::Different: {
+ auto &CurPtr = cast<PointerValue>(Current);
+ auto &WidenedPtr =
+ CurrentEnv.create<PointerValue>(CurPtr.getPointeeLoc());
+ WidenedPtr.setProperty("is_null", CurrentEnv.makeTopBoolValue());
+ return WidenResult{&WidenedPtr, LatticeJoinEffect::Changed};
+ }
+ case ComparisonResult::Unknown:
+ return std::nullopt;
+ }
+ llvm_unreachable("all cases in switch covered");
+ }
};
class WideningTest : public Test {
@@ -846,7 +865,6 @@ TEST_F(WideningTest, JoinDistinctValuesWithDistinctProperties) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3"));
const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
@@ -889,8 +907,6 @@ TEST_F(WideningTest, JoinDistinctValuesWithSameProperties) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results.keys(),
- UnorderedElementsAre("p1", "p2", "p3", "p4"));
const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
@@ -929,19 +945,11 @@ TEST_F(WideningTest, DistinctPointersToTheSameLocationAreEquivalent) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
-
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
- ASSERT_THAT(BarDecl, NotNull());
-
- const auto *FooLoc =
- cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
- const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
- EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
+ const auto &FooLoc =
+ getLocForDecl<ScalarStorageLocation>(ASTCtx, Env, "Foo");
+ const auto &BarVal = getValueForDecl<PointerValue>(ASTCtx, Env, "Bar");
+ EXPECT_EQ(&BarVal.getPointeeLoc(), &FooLoc);
});
}
@@ -963,18 +971,38 @@ TEST_F(WideningTest, DistinctValuesWithSamePropertiesAreEquivalent) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
-
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const auto *FooVal = Env.getValue(*FooDecl);
- EXPECT_EQ(FooVal->getProperty("is_null"),
+ const auto &FooVal = getValueForDecl<Value>(ASTCtx, Env, "Foo");
+ EXPECT_EQ(FooVal.getProperty("is_null"),
&Env.getBoolLiteralValue(false));
});
}
+TEST_F(WideningTest, DistinctValuesWithDifferentPropertiesWidenedToTop) {
+ std::string Code = R"(
+ void target(bool Cond) {
+ int *Foo;
+ int i = 0;
+ Foo = nullptr;
+ while (Cond) {
+ Foo = &i;
+ }
+ (void)0;
+ /*[[p]]*/
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+ const auto &FooVal = getValueForDecl<Value>(ASTCtx, Env, "Foo");
+ ASSERT_THAT(FooVal.getProperty("is_null"), NotNull());
+ EXPECT_TRUE(areEquivalentValues(*FooVal.getProperty("is_null"),
+ Env.makeTopBoolValue()));
+ });
+}
+
class FlowConditionTest : public Test {
protected:
template <typename Matcher>
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 2539d3d..9425647d 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -1916,6 +1916,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsTrailingReturnArrow) {
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[7], tok::arrow, TT_Unknown);
+ Tokens = annotate("__attribute__((cold)) C() : Base(obj->func()) {}");
+ ASSERT_EQ(Tokens.size(), 21u) << Tokens;
+ EXPECT_TOKEN(Tokens[13], tok::arrow, TT_Unknown);
+
// Mixed
Tokens = annotate("auto f() -> int { auto a = b()->c; }");
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 370d99b..bc27b20 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -751,11 +751,6 @@ conformance.</p>
<td class="unknown" align="center">Unknown</td>
</tr>
<tr>
- <td>Floating-point negation and conversion</td>
- <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2416.pdf">N2416</a></td>
- <td class="unknown" align="center">Unknown</td>
- </tr>
- <tr>
<td>Annex F.8 update for implementation extensions and rounding</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2384.pdf">N2384</a></td>
<td class="unknown" align="center">Unknown</td>