diff options
Diffstat (limited to 'clang')
24 files changed, 334 insertions, 113 deletions
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index bef6e9c1..495f2ab 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -32,7 +32,7 @@ Feature Checking Macros ======================= Language extensions can be very useful, but only if you know you can depend on -them. In order to allow fine-grain features checks, we support three builtin +them. In order to allow fine-grained feature checks, we support three builtin function-like macros. This allows you to directly test for a feature in your code without having to resort to something like autoconf or fragile "compiler version checks". @@ -137,7 +137,7 @@ feature) or 0 if not. They can be used like this: .. _langext-has-feature-back-compat: For backward compatibility, ``__has_feature`` can also be used to test -for support for non-standardized features, i.e. features not prefixed ``c_``, +for support for non-standardized features, i.e., features not prefixed ``c_``, ``cxx_`` or ``objc_``. Another use of ``__has_feature`` is to check for compiler features not related @@ -159,7 +159,7 @@ of ``cxx_rvalue_references``. This function-like macro is available in C++20 by default, and is provided as an extension in earlier language standards. It takes a single argument that is the -name of a double-square-bracket-style attribute. The argument can either be a +name of a double-square-bracket-style attribute. The argument can be either a single identifier or a scoped identifier. If the attribute is supported, a nonzero value is returned. If the attribute is a standards-based attribute, this macro returns a nonzero value based on the year and month in which the attribute @@ -320,7 +320,7 @@ To test for this feature, use ``#if defined(__has_include)``: .. code-block:: c++ - // To avoid problem with non-clang compilers not having this macro. + // To avoid problems with non-clang compilers not having this macro. #if defined(__has_include) #if __has_include("myinclude.h") # include "myinclude.h" @@ -345,7 +345,7 @@ or 0 otherwise: # include_next "myinclude.h" #endif - // To avoid problem with non-clang compilers not having this macro. + // To avoid problems with non-clang compilers not having this macro. #if defined(__has_include_next) #if __has_include_next("myinclude.h") # include_next "myinclude.h" @@ -361,7 +361,7 @@ absolute path is used in the file argument. ----------------- This function-like macro takes a string literal that represents a command line -option for a warning and returns true if that is a valid warning option. +option for a warning and returns ``true`` if that is a valid warning option. .. code-block:: c++ @@ -396,7 +396,7 @@ Builtin Macros file. ``__clang__`` - Defined when compiling with Clang + Defined when compiling with Clang. ``__clang_major__`` Defined to the major marketing version number of Clang (e.g., the 2 in @@ -599,7 +599,7 @@ NEON vector types are created using ``neon_vector_type`` and GCC vector types are created using the ``vector_size(N)`` attribute. The argument ``N`` specifies the number of bytes that will be allocated for an -object of this type. The size has to be multiple of the size of the vector +object of this type. The size has to be a multiple of the size of the vector element type. For example: .. code-block:: c++ @@ -620,7 +620,7 @@ element type. For example: Boolean Vectors --------------- -Clang also supports the ext_vector_type attribute with boolean element types in +Clang also supports the ``ext_vector_type`` attribute with boolean element types in C and C++. For example: .. code-block:: c++ @@ -674,7 +674,7 @@ Vector Literals Vector literals can be used to create vectors from a set of scalars, or vectors. Either parentheses or braces form can be used. In the parentheses -form the number of literal values specified must be one, i.e. referring to a +form the number of literal values specified must be one, i.e., referring to a scalar value, or must match the size of the vector type being created. If a single scalar literal value is specified, the scalar literal value will be replicated to all the components of the vector type. In the brackets form any @@ -725,12 +725,12 @@ address &v[i] no no no [#]_ no no See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`. -.. [#] ternary operator(?:) has different behaviors depending on condition - operand's vector type. If the condition is a GNU vector (i.e. __vector_size__), +.. [#] ternary operator(?:) has different behaviors depending on the condition + operand's vector type. If the condition is a GNU vector (i.e., ``__vector_size__``), a NEON vector or an SVE vector, it's only available in C++ and uses normal bool conversions (that is, != 0). If it's an extension (OpenCL) vector, it's only available in C and OpenCL C. - And it selects based on signedness of the condition operands (OpenCL v1.1 s6.3.9). + And it selects based on the signedness of the condition operands (OpenCL v1.1 s6.3.9). .. [#] sizeof can only be used on vector length specific SVE types. .. [#] Clang does not allow the address of an element to be taken while GCC allows this. This is intentional for vectors with a boolean element type and @@ -747,7 +747,7 @@ to perform additional operations on certain scalar and vector types. Let ``T`` be one of the following types: * an integer type (as in C23 6.2.5p22), but excluding enumerated types and ``bool`` -* the standard floating types float or double +* the standard floating types ``float`` or ``double`` * a half-precision floating point type, if one is supported on the target * a vector type. @@ -833,7 +833,7 @@ of different sizes and signs is forbidden in binary and ternary builtins. T __builtin_elementwise_canonicalize(T x) return the platform specific canonical encoding floating point types of a floating-point number T __builtin_elementwise_copysign(T x, T y) return the magnitude of x with the sign of y. floating point types - T __builtin_elementwise_fmod(T x, T y) return The floating-point remainder of (x/y) whose sign floating point types + T __builtin_elementwise_fmod(T x, T y) return the floating-point remainder of (x/y) whose sign floating point types matches the sign of x. T __builtin_elementwise_max(T x, T y) return x or y, whichever is larger integer and floating point types For floating point types, follows semantics of maxNum @@ -948,7 +948,7 @@ Let ``VT`` be a vector type and ``ET`` the element type of ``VT``. Each builtin accesses memory according to a provided boolean mask. These are provided as ``__builtin_masked_load`` and ``__builtin_masked_store``. The first -argument is always boolean mask vector. The ``__builtin_masked_load`` builtin +argument is always a boolean mask vector. The ``__builtin_masked_load`` builtin takes an optional third vector argument that will be used for the result of the masked-off lanes. These builtins assume the memory is unaligned, use ``__builtin_assume_aligned`` if alignment is desired. @@ -1109,7 +1109,7 @@ to ``float``; see below for more information on this emulation. ``__fp16`` and ``_Float16`` both use the binary16 format from IEEE 754-2008, which provides a 5-bit exponent and an 11-bit significand -(counting the implicit leading 1). ``__bf16`` uses the `bfloat16 +(including the implicit leading 1). ``__bf16`` uses the `bfloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_ format, which provides an 8-bit exponent and an 8-bit significand; this is the same exponent range as `float`, just with greatly reduced precision. @@ -1143,7 +1143,7 @@ types with the ``-ffloat16-excess-precision=`` and * ``none``: meaning to perform strict operation-by-operation emulation * ``standard``: meaning that excess precision is permitted under the rules - described in the standard, i.e. never across explicit casts or statements + described in the standard, i.e., never across explicit casts or statements * ``fast``: meaning that excess precision is permitted whenever the optimizer sees an opportunity to avoid truncations; currently this has no effect beyond ``standard`` @@ -1899,7 +1899,7 @@ Type Trait Primitives Type trait primitives are special builtin constant expressions that can be used by the standard C++ library to facilitate or simplify the implementation of -user-facing type traits in the <type_traits> header. +user-facing type traits in the ``<type_traits>`` header. They are not intended to be used directly by user code because they are implementation-defined and subject to change -- as such they're tied closely to @@ -2054,7 +2054,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__is_volatile`` (C++, Embarcadero) * ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a reference of type ``T`` bound to an expression of type ``U`` would bind to a - materialized temporary object. If ``T`` is not a reference type the result + materialized temporary object. If ``T`` is not a reference type, the result is false. Note this trait will also return false when the initialization of ``T`` from ``U`` is ill-formed. Deprecated, use ``__reference_constructs_from_temporary``. @@ -2182,7 +2182,7 @@ Prior to clang-16, the output may only be used safely when the indirect branches are not taken. Query for this difference with ``__has_extension(gnu_asm_goto_with_outputs_full)``. -When using tied-outputs (i.e. outputs that are inputs and outputs, not just +When using tied-outputs (i.e., outputs that are inputs and outputs, not just outputs) with the `+r` constraint, there is a hidden input that's created before the label, so numeric references to operands must account for that. @@ -2361,7 +2361,7 @@ Loading from a ``__weak`` variable always implicitly retains the loaded value. In non-ARC modes, this retain is normally balanced by an implicit autorelease. This autorelease can be suppressed by performing the load in the receiver position of a ``-retain`` -message send (e.g. ``[weakReference retain]``); note that this performs +message send (e.g., ``[weakReference retain]``); note that this performs only a single retain (the retain done when primitively loading from the weak reference). @@ -2562,7 +2562,7 @@ When a method that's introduced in the OS newer than the target OS is called, a .. code-block:: objc void my_fun(NSSomeClass* var) { - // If fancyNewMethod was added in e.g. macOS 10.12, but the code is + // If fancyNewMethod was added in e.g., macOS 10.12, but the code is // built with -mmacos-version-min=10.11, then this unconditional call // will emit a -Wunguarded-availability warning: [var fancyNewMethod]; @@ -2725,7 +2725,7 @@ correctly in any circumstances. It can be used if: metaprogramming algorithms to be able to specify/detect types generically. - the generated kernel binary does not contain indirect calls because they - are eliminated using compiler optimizations e.g. devirtualization. + are eliminated using compiler optimizations e.g., devirtualization. - the selected target supports the function pointer like functionality e.g. most CPU targets. @@ -2755,12 +2755,12 @@ Extension Specification, section 1.2 <https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_. This is not conformant behavior and it can only be used portably when the -functions with variadic prototypes do not get generated in binary e.g. the +functions with variadic prototypes do not get generated in binary e.g., the variadic prototype is used to specify a function type with any number of arguments in metaprogramming algorithms in C++ for OpenCL. This extension can also be used when the kernel code is intended for targets -supporting the variadic arguments e.g. majority of CPU targets. +supporting the variadic arguments e.g., majority of CPU targets. **Example of Use**: @@ -5170,8 +5170,8 @@ __builtin_amdgcn_fence ``__builtin_amdgcn_fence`` emits a fence. -* ``unsigned`` atomic ordering, e.g. ``__ATOMIC_ACQUIRE`` -* ``const char *`` synchronization scope, e.g. ``workgroup`` +* ``unsigned`` atomic ordering, e.g., ``__ATOMIC_ACQUIRE`` +* ``const char *`` synchronization scope, e.g., ``workgroup`` * Zero or more ``const char *`` address spaces names. The address spaces arguments must be one of the following string literals: @@ -5205,7 +5205,7 @@ boolean argument as a bit for every lane of the current wave that is currently active (i.e., that is converged with the executing thread), and a 0 bit for every lane that is not active. -The result is uniform, i.e. it is the same in every active thread of the wave. +The result is uniform, i.e., it is the same in every active thread of the wave. __builtin_amdgcn_inverse_ballot_w{32,64} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -5374,7 +5374,7 @@ followed by ``off`` or ``on``. All function definitions in the region between an ``off`` and the following ``on`` will be decorated with the ``optnone`` attribute unless doing so would -conflict with explicit attributes already present on the function (e.g. the +conflict with explicit attributes already present on the function (e.g., the ones that control inlining). .. code-block:: c++ @@ -5472,12 +5472,12 @@ provides options for vectorization, interleaving, predication, unrolling and distribution. Loop hints can be specified before any loop and will be ignored if the optimization is not safe to apply. -There are loop hints that control transformations (e.g. vectorization, loop +There are loop hints that control transformations (e.g., vectorization, loop unrolling) and there are loop hints that set transformation options (e.g. ``vectorize_width``, ``unroll_count``). Pragmas setting transformation options -imply the transformation is enabled, as if it was enabled via the corresponding -transformation pragma (e.g. ``vectorize(enable)``). If the transformation is -disabled (e.g. ``vectorize(disable)``), that takes precedence over +imply the transformation is enabled, as if it were enabled via the corresponding +transformation pragma (e.g., ``vectorize(enable)``). If the transformation is +disabled (e.g., ``vectorize(disable)``), that takes precedence over transformations option pragmas implying that transformation. Vectorization, Interleaving, and Predication @@ -5704,7 +5704,7 @@ operation when supported by the target. The pragma can take three values: ``on``, ``fast`` and ``off``. The ``on`` option is identical to using ``#pragma STDC FP_CONTRACT(ON)`` and it allows fusion as specified the language standard. The ``fast`` option allows fusion -in cases when the language standard does not make this possible (e.g. across +in cases when the language standard does not make this possible (e.g., across statements in C). .. code-block:: c++ @@ -5859,14 +5859,14 @@ and ``ignore_denormal_mode``, each optionally prefixed with ``no_``. The meaning are as follows: - ``remote_memory`` means atomic operations may be performed on remote - memory, i.e. memory accessed through off-chip interconnects (e.g., PCIe). + memory, i.e., memory accessed through off-chip interconnects (e.g., PCIe). On ROCm platforms using HIP, remote memory refers to memory accessed via PCIe and is subject to specific atomic operation support. See `ROCm PCIe Atomics <https://rocm.docs.amd.com/en/latest/conceptual/ pcie-atomics.html>`_ for further details. Prefixing with ``no_remote_memory`` indicates that atomic operations should not be performed on remote memory. - ``fine_grained_memory`` means atomic operations may be performed on fine-grained - memory, i.e. memory regions that support fine-grained coherence, where updates to + memory, i.e., memory regions that support fine-grained coherence, where updates to memory are visible to other parts of the system even while modifications are ongoing. For example, in HIP, fine-grained coherence ensures that host and device share up-to-date data without explicit synchronization (see @@ -6088,7 +6088,7 @@ match rules are specified after the attribute. The compiler expects an identifier that corresponds to the subject set specifier. The ``apply_to`` specifier is currently the only supported subject set specifier. It allows you to specify match rules that form a subset of the attribute's allowed subject -set, i.e. the compiler doesn't require all of the attribute's subjects. For +set, i.e., the compiler doesn't require all of the attribute's subjects. For example, an attribute like ``[[nodiscard]]`` whose subject set includes ``enum``, ``record`` and ``hasType(functionType)``, requires the presence of at least one of these rules after ``apply_to``: diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 649fba9..27ff5ab 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -1061,8 +1061,8 @@ InlineCommandRenderKind Sema::getInlineCommandRenderKind(StringRef Name) const { return llvm::StringSwitch<InlineCommandRenderKind>(Name) .Case("b", InlineCommandRenderKind::Bold) - .Cases("c", "p", InlineCommandRenderKind::Monospaced) - .Cases("a", "e", "em", InlineCommandRenderKind::Emphasized) + .Cases({"c", "p"}, InlineCommandRenderKind::Monospaced) + .Cases({"a", "e", "em"}, InlineCommandRenderKind::Emphasized) .Case("anchor", InlineCommandRenderKind::Anchor) .Default(InlineCommandRenderKind::Normal); } diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index c2d1bc1..a97e934 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -811,10 +811,10 @@ bool AArch64TargetInfo::validateCpuSupports(StringRef FeatureStr) const { bool AArch64TargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch<bool>(Feature) - .Cases("aarch64", "arm64", "arm", true) + .Cases({"aarch64", "arm64", "arm"}, true) .Case("fmv", HasFMV) .Case("fp", FPU & FPUMode) - .Cases("neon", "simd", FPU & NeonMode) + .Cases({"neon", "simd"}, FPU & NeonMode) .Case("jscvt", HasJSCVT) .Case("fcma", HasFCMA) .Case("rng", HasRandGen) @@ -829,8 +829,8 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { .Case("cssc", HasCSSC) .Case("sha2", HasSHA2) .Case("sha3", HasSHA3) - .Cases("aes", "pmull", HasAES) - .Cases("fp16", "fullfp16", HasFullFP16) + .Cases({"aes", "pmull"}, HasAES) + .Cases({"fp16", "fullfp16"}, HasFullFP16) .Case("dit", HasDIT) .Case("dpb", HasCCPP) .Case("dpb2", HasCCDP) @@ -859,9 +859,9 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { .Case("memtag", HasMTE) .Case("sb", HasSB) .Case("predres", HasPredRes) - .Cases("ssbs", "ssbs2", HasSSBS) + .Cases({"ssbs", "ssbs2"}, HasSSBS) .Case("bti", HasBTI) - .Cases("ls64", "ls64_v", "ls64_accdata", HasLS64) + .Cases({"ls64", "ls64_v", "ls64_accdata"}, HasLS64) .Case("wfxt", HasWFxT) .Case("rcpc3", HasRCPC3) .Case("fp8", HasFP8) diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 9f3a4cd..846b240 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -122,41 +122,41 @@ public: .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) .Case("a2", ArchDefineA2) - .Cases("power3", "pwr3", ArchDefinePpcgr) - .Cases("power4", "pwr4", + .Cases({"power3", "pwr3"}, ArchDefinePpcgr) + .Cases({"power4", "pwr4"}, ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) .Cases("power5", "pwr5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power5x", "pwr5x", + .Cases({"power5x", "pwr5x"}, ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power6", "pwr6", - ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power6x", "pwr6x", + .Cases({"power6", "pwr6"}, ArchDefinePwr6 | ArchDefinePwr5x | + ArchDefinePwr5 | ArchDefinePwr4 | + ArchDefinePpcgr | ArchDefinePpcsq) + .Cases({"power6x", "pwr6x"}, ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power7", "pwr7", - ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) + .Cases({"power7", "pwr7"}, ArchDefinePwr7 | ArchDefinePwr6 | + ArchDefinePwr5x | ArchDefinePwr5 | + ArchDefinePwr4 | ArchDefinePpcgr | + ArchDefinePpcsq) // powerpc64le automatically defaults to at least power8. - .Cases("power8", "pwr8", "ppc64le", + .Cases({"power8", "pwr8", "ppc64le"}, ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power9", "pwr9", + .Cases({"power9", "pwr9"}, ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power10", "pwr10", + .Cases({"power10", "pwr10"}, ArchDefinePwr10 | ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Cases("power11", "pwr11", + .Cases({"power11", "pwr11"}, ArchDefinePwr11 | ArchDefinePwr10 | ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 88aef89..50d4c03 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -671,9 +671,12 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, return RValue::get(results[0]); } - case cir::TEK_Complex: - cgm.errorNYI(loc, "unsupported evaluation kind of function call result"); - return getUndefRValue(retTy); + case cir::TEK_Complex: { + mlir::ResultRange results = theCall->getOpResults(); + assert(!results.empty() && + "Expected at least one result for complex rvalue"); + return RValue::getComplex(results[0]); + } } llvm_unreachable("Invalid evaluation kind"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.h b/clang/lib/CIR/CodeGen/CIRGenCleanup.h index 9acf8b1..61a09a5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCleanup.h +++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.h @@ -15,6 +15,7 @@ #define CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H #include "Address.h" +#include "CIRGenModule.h" #include "EHScopeStack.h" #include "mlir/IR/Value.h" @@ -257,5 +258,53 @@ inline void EHScopeStack::popCatch() { deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers())); } +/// The exceptions personality for a function. +struct EHPersonality { + const char *personalityFn = nullptr; + + // If this is non-null, this personality requires a non-standard + // function for rethrowing an exception after a catchall cleanup. + // This function must have prototype void(void*). + const char *catchallRethrowFn = nullptr; + + static const EHPersonality &get(CIRGenModule &cgm, + const clang::FunctionDecl *fd); + static const EHPersonality &get(CIRGenFunction &cgf); + + static const EHPersonality GNU_C; + static const EHPersonality GNU_C_SJLJ; + static const EHPersonality GNU_C_SEH; + static const EHPersonality GNU_ObjC; + static const EHPersonality GNU_ObjC_SJLJ; + static const EHPersonality GNU_ObjC_SEH; + static const EHPersonality GNUstep_ObjC; + static const EHPersonality GNU_ObjCXX; + static const EHPersonality NeXT_ObjC; + static const EHPersonality GNU_CPlusPlus; + static const EHPersonality GNU_CPlusPlus_SJLJ; + static const EHPersonality GNU_CPlusPlus_SEH; + static const EHPersonality MSVC_except_handler; + static const EHPersonality MSVC_C_specific_handler; + static const EHPersonality MSVC_CxxFrameHandler3; + static const EHPersonality GNU_Wasm_CPlusPlus; + static const EHPersonality XL_CPlusPlus; + static const EHPersonality ZOS_CPlusPlus; + + /// Does this personality use landingpads or the family of pad instructions + /// designed to form funclets? + bool usesFuncletPads() const { + return isMSVCPersonality() || isWasmPersonality(); + } + + bool isMSVCPersonality() const { + return this == &MSVC_except_handler || this == &MSVC_C_specific_handler || + this == &MSVC_CxxFrameHandler3; + } + + bool isWasmPersonality() const { return this == &GNU_Wasm_CPlusPlus; } + + bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; } +}; + } // namespace clang::CIRGen #endif // CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 717a3e0..67f46ff 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -18,6 +18,171 @@ using namespace clang; using namespace clang::CIRGen; +const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr}; +const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0", + nullptr}; +const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0", + nullptr}; +const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0", + nullptr}; +const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0", + nullptr}; +const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = { + "__gxx_personality_sj0", nullptr}; +const EHPersonality EHPersonality::GNU_CPlusPlus_SEH = { + "__gxx_personality_seh0", nullptr}; +const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", + "objc_exception_throw"}; +const EHPersonality EHPersonality::GNU_ObjC_SJLJ = { + "__gnu_objc_personality_sj0", "objc_exception_throw"}; +const EHPersonality EHPersonality::GNU_ObjC_SEH = { + "__gnu_objc_personality_seh0", "objc_exception_throw"}; +const EHPersonality EHPersonality::GNU_ObjCXX = { + "__gnustep_objcxx_personality_v0", nullptr}; +const EHPersonality EHPersonality::GNUstep_ObjC = { + "__gnustep_objc_personality_v0", nullptr}; +const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3", + nullptr}; +const EHPersonality EHPersonality::MSVC_C_specific_handler = { + "__C_specific_handler", nullptr}; +const EHPersonality EHPersonality::MSVC_CxxFrameHandler3 = { + "__CxxFrameHandler3", nullptr}; +const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = { + "__gxx_wasm_personality_v0", nullptr}; +const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1", + nullptr}; +const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2", + nullptr}; + +static const EHPersonality &getCPersonality(const TargetInfo &target, + const CodeGenOptions &cgOpts) { + const llvm::Triple &triple = target.getTriple(); + if (triple.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + if (cgOpts.hasSjLjExceptions()) + return EHPersonality::GNU_C_SJLJ; + if (cgOpts.hasDWARFExceptions()) + return EHPersonality::GNU_C; + if (cgOpts.hasSEHExceptions()) + return EHPersonality::GNU_C_SEH; + return EHPersonality::GNU_C; +} + +static const EHPersonality &getObjCPersonality(const TargetInfo &target, + const LangOptions &langOpts, + const CodeGenOptions &cgOpts) { + const llvm::Triple &triple = target.getTriple(); + if (triple.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + + switch (langOpts.ObjCRuntime.getKind()) { + case ObjCRuntime::FragileMacOSX: + return getCPersonality(target, cgOpts); + case ObjCRuntime::MacOSX: + case ObjCRuntime::iOS: + case ObjCRuntime::WatchOS: + return EHPersonality::NeXT_ObjC; + case ObjCRuntime::GNUstep: + if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) + return EHPersonality::GNUstep_ObjC; + [[fallthrough]]; + case ObjCRuntime::GCC: + case ObjCRuntime::ObjFW: + if (cgOpts.hasSjLjExceptions()) + return EHPersonality::GNU_ObjC_SJLJ; + if (cgOpts.hasSEHExceptions()) + return EHPersonality::GNU_ObjC_SEH; + return EHPersonality::GNU_ObjC; + } + llvm_unreachable("bad runtime kind"); +} + +static const EHPersonality &getCXXPersonality(const TargetInfo &target, + const CodeGenOptions &cgOpts) { + const llvm::Triple &triple = target.getTriple(); + if (triple.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + if (triple.isOSAIX()) + return EHPersonality::XL_CPlusPlus; + if (cgOpts.hasSjLjExceptions()) + return EHPersonality::GNU_CPlusPlus_SJLJ; + if (cgOpts.hasDWARFExceptions()) + return EHPersonality::GNU_CPlusPlus; + if (cgOpts.hasSEHExceptions()) + return EHPersonality::GNU_CPlusPlus_SEH; + if (cgOpts.hasWasmExceptions()) + return EHPersonality::GNU_Wasm_CPlusPlus; + return EHPersonality::GNU_CPlusPlus; +} + +/// Determines the personality function to use when both C++ +/// and Objective-C exceptions are being caught. +static const EHPersonality &getObjCXXPersonality(const TargetInfo &target, + const LangOptions &langOpts, + const CodeGenOptions &cgOpts) { + if (target.getTriple().isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + + switch (langOpts.ObjCRuntime.getKind()) { + // In the fragile ABI, just use C++ exception handling and hope + // they're not doing crazy exception mixing. + case ObjCRuntime::FragileMacOSX: + return getCXXPersonality(target, cgOpts); + + // The ObjC personality defers to the C++ personality for non-ObjC + // handlers. Unlike the C++ case, we use the same personality + // function on targets using (backend-driven) SJLJ EH. + case ObjCRuntime::MacOSX: + case ObjCRuntime::iOS: + case ObjCRuntime::WatchOS: + return getObjCPersonality(target, langOpts, cgOpts); + + case ObjCRuntime::GNUstep: + return EHPersonality::GNU_ObjCXX; + + // The GCC runtime's personality function inherently doesn't support + // mixed EH. Use the ObjC personality just to avoid returning null. + case ObjCRuntime::GCC: + case ObjCRuntime::ObjFW: + return getObjCPersonality(target, langOpts, cgOpts); + } + llvm_unreachable("bad runtime kind"); +} + +static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) { + return triple.getArch() == llvm::Triple::x86 + ? EHPersonality::MSVC_except_handler + : EHPersonality::MSVC_C_specific_handler; +} + +const EHPersonality &EHPersonality::get(CIRGenModule &cgm, + const FunctionDecl *fd) { + const llvm::Triple &triple = cgm.getTarget().getTriple(); + const LangOptions &langOpts = cgm.getLangOpts(); + const CodeGenOptions &cgOpts = cgm.getCodeGenOpts(); + const TargetInfo &target = cgm.getTarget(); + + // Functions using SEH get an SEH personality. + if (fd && fd->usesSEHTry()) + return getSEHPersonalityMSVC(triple); + + if (langOpts.ObjC) { + return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts) + : getObjCPersonality(target, langOpts, cgOpts); + } + return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts) + : getCPersonality(target, cgOpts); +} + +const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) { + const auto *fg = cgf.curCodeDecl; + // For outlined finallys and filters, use the SEH personality in case they + // contain more SEH. This mostly only affects finallys. Filters could + // hypothetically use gnu statement expressions to sneak in nested SEH. + fg = fg ? fg : cgf.curSEHParent.getDecl(); + return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg)); +} + void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) { const llvm::Triple &triple = getTarget().getTriple(); if (cgm.getLangOpts().OpenMPIsTargetDevice && diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index d791130..c3fcd1a6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -120,6 +120,8 @@ public: /// Tracks function scope overall cleanup handling. EHScopeStack ehStack; + GlobalDecl curSEHParent; + llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *> lambdaCaptureFields; clang::FieldDecl *lambdaThisCaptureField = nullptr; diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index 227c6a0..6a6a4ee 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -502,8 +502,8 @@ bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, if (Arg *A = Args.getLastArg(options::OPT_mmsa)) if (A->getOption().matches(options::OPT_mmsa)) UseFPXX = llvm::StringSwitch<bool>(CPUName) - .Cases("mips32r2", "mips32r3", "mips32r5", false) - .Cases("mips64r2", "mips64r3", "mips64r5", false) + .Cases({"mips32r2", "mips32r3", "mips32r5"}, false) + .Cases({"mips64r2", "mips64r3", "mips64r5"}, false) .Default(UseFPXX); return UseFPXX; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 727af69..ec8dcdc 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -663,11 +663,11 @@ static std::string getAMDGPUTargetGPU(const llvm::Triple &T, if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { auto GPUName = getProcessorFromTargetID(T, A->getValue()); return llvm::StringSwitch<std::string>(GPUName) - .Cases("rv630", "rv635", "r600") - .Cases("rv610", "rv620", "rs780", "rs880") + .Cases({"rv630", "rv635"}, "r600") + .Cases({"rv610", "rv620", "rs780"}, "rs880") .Case("rv740", "rv770") .Case("palm", "cedar") - .Cases("sumo", "sumo2", "sumo") + .Cases({"sumo", "sumo2"}, "sumo") .Case("hemlock", "cypress") .Case("aruba", "cayman") .Default(GPUName.str()); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a8a9c51..1d0dfd0b 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3791,18 +3791,12 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, if (Current.is(TT_FunctionDeclarationName)) return true; - if (!Current.Tok.getIdentifierInfo()) + if (Current.isNoneOf(tok::identifier, tok::kw_operator)) return false; const auto *Prev = Current.getPreviousNonComment(); assert(Prev); - if (Prev->is(tok::coloncolon)) - Prev = Prev->Previous; - - if (!Prev) - return false; - const auto &Previous = *Prev; if (const auto *PrevPrev = Previous.getPreviousNonComment(); @@ -3851,6 +3845,8 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, // Find parentheses of parameter list. if (Current.is(tok::kw_operator)) { + if (Line.startsWith(tok::kw_friend)) + return true; if (Previous.Tok.getIdentifierInfo() && Previous.isNoneOf(tok::kw_return, tok::kw_co_return)) { return true; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d2cb751..bd36eb4 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3214,7 +3214,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, DashX = llvm::StringSwitch<InputKind>(XValue) .Case("cpp-output", InputKind(Language::C).getPreprocessed()) .Case("assembler-with-cpp", Language::Asm) - .Cases("ast", "pcm", "precompiled-header", + .Cases({"ast", "pcm", "precompiled-header"}, InputKind(Language::Unknown, InputKind::Precompiled)) .Case("ir", Language::LLVM_IR) .Case("cir", Language::CIR) diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 5b08d7f..1c06152 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1283,10 +1283,10 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, // Per tweaked N3660, "il", "i", and "if" are also used in the library. // In C++2a "d" and "y" are used in the library. return llvm::StringSwitch<bool>(Suffix) - .Cases("h", "min", "s", true) - .Cases("ms", "us", "ns", true) - .Cases("il", "i", "if", true) - .Cases("d", "y", LangOpts.CPlusPlus20) + .Cases({"h", "min", "s"}, true) + .Cases({"ms", "us", "ns"}, true) + .Cases({"il", "i", "if"}, true) + .Cases({"d", "y"}, LangOpts.CPlusPlus20) .Default(false); } diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index 40985f4..6439e6c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -151,12 +151,10 @@ void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE, return; SubChecker SC = - llvm::StringSwitch<SubChecker>(Name) - .Cases("dispatch_once", - "_dispatch_once", - "dispatch_once_f", - &MacOSXAPIChecker::CheckDispatchOnce) - .Default(nullptr); + llvm::StringSwitch<SubChecker>(Name) + .Cases({"dispatch_once", "_dispatch_once", "dispatch_once_f"}, + &MacOSXAPIChecker::CheckDispatchOnce) + .Default(nullptr); if (SC) (this->*SC)(C, CE, Name); diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 4e89af4..3fb78dc 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1468,3 +1468,30 @@ void calling_function_with_default_arg() { // OGCG: store float 0x40019999A0000000, ptr %[[DEFAULT_ARG_IMAG_PTR]], align 4 // OGCG: %[[TMP_DEFAULT_ARG:.*]] = load <2 x float>, ptr %[[DEFAULT_ARG_ADDR]], align 4 // OGCG: call void @_Z33function_with_complex_default_argCf(<2 x float> {{.*}} %[[TMP_DEFAULT_ARG]]) + +void calling_function_that_return_complex() { + float _Complex a = complex_type_return_type(); +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init] +// CIR: %[[RESULT:.*]] = cir.call @_Z24complex_type_return_typev() : () -> !cir.complex<!cir.float> +// CIR: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering, + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[RESULT:.*]] = call { float, float } @_Z24complex_type_return_typev() +// LLVM: store { float, float } %[[RESULT]], ptr %[[A_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[RESULT_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[RESULT:.*]] = call noundef <2 x float> @_Z24complex_type_return_typev() +// OGCG: store <2 x float> %[[RESULT]], ptr %[[RESULT_ADDR]], align 4 +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_REAL:.*]] = load float, ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT_ADDR]], i32 0, i32 1 +// OGCG: %[[RESULT_IMAG:.*]] = load float, ptr %[[RESULT_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store float %[[RESULT_REAL]], ptr %[[A_REAL_PTR]], align 4 +// OGCG: store float %[[RESULT_IMAG]], ptr %[[A_IMAG_PTR]], align 4 diff --git a/clang/test/Driver/config-file3.c b/clang/test/Driver/config-file3.c index f359e02..c9b26763 100644 --- a/clang/test/Driver/config-file3.c +++ b/clang/test/Driver/config-file3.c @@ -1,9 +1,5 @@ // Needs symlinks // UNSUPPORTED: system-windows -// env -u is not supported on AIX. -// TODO(boomanaiden154): Remove this once we have switched over to lit's -// internal shell which does support env -u. -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // REQUIRES: x86-registered-target // RUN: rm -rf %t && mkdir %t diff --git a/clang/test/Driver/config-zos.c b/clang/test/Driver/config-zos.c index a21753e..055c4c9 100644 --- a/clang/test/Driver/config-zos.c +++ b/clang/test/Driver/config-zos.c @@ -1,9 +1,5 @@ // Needs symlinks // UNSUPPORTED: system-windows -// env -u is not supported on AIX. -// TODO(boomanaiden154): Remove this once we have switched over to lit's -// internal shell which does support env -u. -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // REQUIRES: systemz-registered-target // RUN: rm -rf %t && mkdir %t diff --git a/clang/test/Driver/config-zos1.c b/clang/test/Driver/config-zos1.c index 9dd6f55..cf4f13b 100644 --- a/clang/test/Driver/config-zos1.c +++ b/clang/test/Driver/config-zos1.c @@ -1,8 +1,4 @@ // UNSUPPORTED: system-windows -// env -u is not supported on AIX. -// TODO(boomanaiden154): Remove this once we have switched over to lit's -// internal shell which does support env -u. -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // REQUIRES: systemz-registered-target // RUN: export CLANG_CONFIG_PATH=%S/Inputs/config-zos diff --git a/clang/test/Modules/crash-vfs-path-symlink-component.m b/clang/test/Modules/crash-vfs-path-symlink-component.m index 45a6865..4cc4467 100644 --- a/clang/test/Modules/crash-vfs-path-symlink-component.m +++ b/clang/test/Modules/crash-vfs-path-symlink-component.m @@ -1,9 +1,5 @@ // Needs symlinks // UNSUPPORTED: system-windows -// env -u is not supported on AIX. -// TODO(boomanaiden154): Remove this once we have switched over to lit's -// internal shell which does support env -u. -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // REQUIRES: crash-recovery // FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? diff --git a/clang/test/Modules/crash-vfs-path-traversal.m b/clang/test/Modules/crash-vfs-path-traversal.m index 8ab2475..680cda3 100644 --- a/clang/test/Modules/crash-vfs-path-traversal.m +++ b/clang/test/Modules/crash-vfs-path-traversal.m @@ -2,10 +2,6 @@ // UNSUPPORTED: ms-sdk, target={{.*-(ps4|ps5)}} // Some assertions in this test use Linux style (/) file paths. // UNSUPPORTED: system-windows -// env -u is not supported on AIX. -// TODO(boomanaiden154): Remove this once we have switched over to lit's -// internal shell which does support env -u. -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // FIXME: Canonicalizing paths to remove relative traversal components // currenty fails a unittest on windows and is disable by default. diff --git a/clang/test/Modules/crash-vfs-relative-overlay.m b/clang/test/Modules/crash-vfs-relative-overlay.m index 048c65b..3684924 100644 --- a/clang/test/Modules/crash-vfs-relative-overlay.m +++ b/clang/test/Modules/crash-vfs-relative-overlay.m @@ -1,9 +1,5 @@ // UNSUPPORTED: system-windows // REQUIRES: crash-recovery -// env -u is not supported on AIX. -// TODO(boomanaiden154): Remove this once we have switched over to lit's -// internal shell which does support env -u. -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? // XFAIL: target={{.*-windows-gnu}} diff --git a/clang/unittests/Driver/MultilibBuilderTest.cpp b/clang/unittests/Driver/MultilibBuilderTest.cpp index 0c1e806..ebcbee7 100644 --- a/clang/unittests/Driver/MultilibBuilderTest.cpp +++ b/clang/unittests/Driver/MultilibBuilderTest.cpp @@ -61,7 +61,7 @@ TEST(MultilibBuilderTest, Construction3) { MultilibBuilder().flag("-f1").flag("-f2").flag("-f3", /*Disallow=*/true); for (const std::string &A : M.flags()) { ASSERT_TRUE(llvm::StringSwitch<bool>(A) - .Cases("-f1", "-f2", "!f3", true) + .Cases({"-f1", "-f2", "!f3"}, true) .Default(false)); } } diff --git a/clang/unittests/Driver/MultilibTest.cpp b/clang/unittests/Driver/MultilibTest.cpp index 4c11e6a..ebb8611 100644 --- a/clang/unittests/Driver/MultilibTest.cpp +++ b/clang/unittests/Driver/MultilibTest.cpp @@ -131,7 +131,7 @@ TEST(MultilibTest, Construction3) { E = M.flags().end(); I != E; ++I) { ASSERT_TRUE(llvm::StringSwitch<bool>(*I) - .Cases("+f1", "+f2", "-f3", true) + .Cases({"+f1", "+f2", "-f3"}, true) .Default(false)); } } diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index f363738..ca99940 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1129,6 +1129,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) { ASSERT_EQ(Tokens.size(), 7u) << Tokens; // Not TT_FunctionDeclarationName. EXPECT_TOKEN(Tokens[3], tok::kw_operator, TT_Unknown); + + Tokens = annotate("SomeAPI::operator()();"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + // Not TT_FunctionDeclarationName. + EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown); } TEST_F(TokenAnnotatorTest, OverloadedOperatorInTemplate) { |
